nRF52 Low Level Interface Library

The nRF52 microcontroller used in Puck.js 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.

PPI lets you connect an event (eg. a pin changing state) to a task (eg. increment the counter). All of this is done without the processor being involved, allowing for very fast and also very power efficient peripheral use.

Check out the chip's reference manual for more information.

This library provides a low level interface to PPI and some of the nRF52's peripherals.

Note: Failure to 'shut down' peripherals when not in use could drastically increase the nRF52's power consumption.

Basic Usage

  • Initialise a peripheral to create events
  • Initialise a peripheral you want to send tasks to
  • Set up and Enable a PPI to wire the two together

For instance the following will count the number of times the BTN pin changes state:

var ll = require("NRF52LL");
// Source of events - the button
var btn = ll.gpiote(0, {type:"event",pin:BTN,lo2hi:1,hi2lo:1});
// A place to recieve Tasks - a counter
var ctr = ll.timer(3,{type:"counter"});
// Set up and enable PPI
ll.ppiEnable(0, btn.eIn, ctr.tCount);
/* This function triggers a Task by hand to 'capture' the counter's
value. It can then be read back from the relevant `cc` register */ 
function getCtr() {
  poke32(ctr.tCapture[0],1);
  return peek32(ctr.cc[0]);
}

Or the following will create a square wave on pin D0, with the inverse of the square wave on D1:

var ll = require("NRF52LL");
// set up D0 and D1 as outputs
digitalWrite(D0,0);
digitalWrite(D1,0);
// create two 'toggle' tasks, one for each pin
var t0 = ll.gpiote(0, {type:"task",pin:D0,lo2hi:1,hi2lo:1,initialState:0});
var t1 = ll.gpiote(1, {type:"task",pin:D1,lo2hi:1,hi2lo:1,initialState:1});
// create a timer that counts up to 1000 and back at full speed
var tmr = ll.timer(3,{cc:[1000],cc0clear:1});
// use two PPI to trigger toggle events
ll.ppiEnable(0, tmr.eCompare[0], t0.tOut);
ll.ppiEnable(1, tmr.eCompare[0], t1.tOut);
// Manually trigger a task to start the timer
poke32(tmr.tStart,1);

Reference

/* GPIO Tasks and Events
  ch can be between 0 and 7 for low power GPIO
  opts is {
    type : "event"/"task", // default is event
    pin : D0, // pin number to use,
    lo2hi : 0/1, // default 0, trigger on low-high transition
    hi2lo : 0/1, // default 0, trigger on high-low transition
    initialState : 0, // default 0, initial pin state when toggling states
  }
  returns {
    config,// address of config register
    tOut,  // task to set/toggle pin (lo2hi/hi2lo)
    tSet,  // task to set pin to 1 
    tClr,  // task to set pin to 0
    eIn    // event when GPIO changes
  }
*/
exports.gpiote = function (ch, opts) { ... }

/* 32 bit timers
  ch can be 0..4
  opts is {
    mode : "counter"/"timer", // default = timer
    bits : 8/16/24/32, // default = 32
    prescaler : 0..9, // default = 0
    cc : [5,6,7,8,9,10], // 6 (or less) cpature/compare regs
    cc0clear : true, // if cc[0] matches, clear the timer
    cc3stop : true, // if cc[0] matches, stop the timer
    // for cc0..cc5
  };
  returns {
      shorts, // address of shortcut register
      mode, // address of mode register
      bitmode, // address of bitmode
      prescaler, // address of prescaler register
      cc, // array of 6 addresses of capture/compare registers
      tStart, // address of START task
      tStop, // address of STOP task
      tCount, // address of COUNT task
      tClear, // address of CLEAR task
      tShutdown, // address of SHUTDOWN task
      tCapture, // array of 6 addresses of capture tasks 
      eCompare, // array of 6 addresses of compare events
  }
*/
exports.timer = function (ch, opts) { ... }

/* Set up and enable a PPI channel (0..15) - give it the address of the 
event and task required
*/
exports.ppiEnable = function (ch, event, task) { ... }

// Disable a PPI channel
exports.ppiDisable = function (ch) { ... }

// Check if a PPI channel is enabled
exports.ppiIsEnabled = function (ch) { ... }

This page is auto-generated from GitHub. If you see any mistakes or have suggestions, please let us know.