You might wonder what the hell I have been doing all this week.  

I think we can confidently predict TS06 will run out of program space early.  
It has to have BLE drivers, and DW drivers as well as all the other sensor stuff, and analysis software.  While we wait for a Nordic processor with more memory I will probably have to partition the code development – i.e. develop and test parts of the code independently, and finally cherry-pick and squeeze bits of code to make the TS06.  (Of course, the BeSpoon module has the advantage that a lot of the code that is outside the DecaWave module is inside the BeSpoon module, but who knows if BeSpoon will last much longer?) 
I tried partitioning thing with TS02..5.  But the toolkit was more primitive and made it hard to share code between different independent threads of development.  For example, I had a code base that was designed to explore and test the hardware, and another for the networking, and another that integrated parts of the others to make TS.  But it was so hard to partition the code between the two different applications, and back it up each night.  Fortunately the Atmel 256K processor came along, and so I was able to do everything in one module with some squeezing.  Indeed the final code base for TS05 is actually called HWTest rather than TS!  So the code contains a lot of stuff that isn't really needed, and of course soaks up valuable memory.
I already have several threads going that I am trying to keep separate for simplicity and speed.  But keeping all the source libraries (DW, Nordic) separate and shareable took some more study, and created it's own snags.   Also I will need to keep DW and BeSpoon developments separate.  Then I need to be able to keep the developments for each board definitions separate.
So organizing the development tools has taken way more time than I ever thought possible – exacerbated by my own ignorance.
I think I have it kind of organised now, but time will tell.  I'm also backing it up to a git repository so I can move the code base between desktop, and laptop in anticipation of going to the UK.
It is truly amazing how much time this kind of stuff soaks up.

Given that we can now buy modules containing an IMU the rationale for building a Dewbly is called into question – unless we do it for the hell of it.

The technical question to be answered is not quite covered on pages38-39 of the DW1000 User Manual in section 4.5.1 which shows Sniff Mode and Low duty-cycle SNIFF mode.
The basic idea behind sniffing is that the radio turns on and listens at intervals that regularly sample the ether, listening for traffic.  The sniff interval and duration are determined by the peer's anticipated transmission pattern.
So if A transmits a one second packet every ten seconds.  Then B can sniff the ether briefly every second, and guarantee to be listening when the packet is transmitted.  Notice that this does not guarantee that it is heard, or received without error.
The principle is explained well, but unlike at other places in this manual I found no illustrative examples of power usage.   I wonder if we dare ask DW to point us at the relevant information, or to provide some estimates of SNIFF power budget for different latencies?  What do you think?
One reason we are using a Nordic M0 is that it provides an alternative method for sniffing that ought to be lower powered because of the physics of the radio.  But that's not been confirmed.
Maybe we could ask them for an off-the-cuff guestimate of how DW sniffing would compare with (er… to take a random example)  BLE sniffing for a range of duty cycles.
//Mik

http://www.openrtls.com/shop

Have a bunch of interesting products.

A NEYO anchor to go into a wall socket is 85 Euros.

A tag with an IMU is only 27 Euros and contains an

DW1000 UWB transceiver
Cortex M4F, 84MHz, 512kB flash, 80kB RAM

This one looks particularly interesting.
IMU only means accelerometer!
2ppm clock seems good.

Tag2747MIPHQ
  • M=MircoController onboard,
  • I=Inertia Measurement Unit (optional)
  • P=Pressure sensor (optional)
  • H=Humidity, Temperature sensor (optional)
  • Q=Qi wireless charger circuit without external coil (optional)

DW1000 UWB transceiver
EPC 2 active RFID
Cortex M3, 128kB flash, 64kB RAM
Accelerometer LIS3DSH
2 DAC (1Mbit 10 bit)
1 ADC (400ksps)
1 GPIO
1 I2C, 1 uart
Integrated UWB antenna
Li-Po Battery connector (BM03B)
micro-USB port
30nA sleep current1 (RAM retention/2ppm clock)2
dimensions: 27 x 47 mm

1 = optional
2 = standard sleep current approx 200nA, standby current with IMU active approx 5uA

I'm just looking at the DW manual pages 27-32.  It looks pretty informative, but on the other hand I don't actually understand it.  I wondered if you do?

p28 it says that if we found some way to turn the DW power off then it would consume zero, and would take no longer to start up than if it were in deepsleep (50nA) or sleep(1uA).  The downside of "off" is that it would be necessary to reload all the configuration – which is a bunch of SPI activity, so the tradeoff depends on the time between wakeups.  In a footnote it says the osc. startup delay is 3ms.
But on p29 the sleep currents are all doubled?  Does that mean they are assukming a 2s sleep?  If so, why?  It also says there is a 5ms osc. startup delay.
On p30 there is a table of TX range vs. current. All the ranges are in access of 40 meters which seems plenty for our needs,  but I wonder if the range will be attenuated indoors?  I expects so.
The best ranges (in descending order) are in modes 10,12,14, 2, 5.  The TX powers are ~36,38,28,34,34 mA (reading from the range graph).  But the table at the top of the page says 79,75,65,68,50mA (for channel2) and slightly more for channel #5.  Why the difference?
And then the chart on p31 profiles a complete transmission, and the figures are not consistent yet again.
OSC startup/PLL lock takes 2.007ms (not 5ms).  
And in any case, is the total power used on p31
mA W @ 3.3V duration us uW seconds
3 0.0099 2000 19.8
12 0.0396 7 0.2772
15 0.0495 10 0.495
65 0.2145 135 28.9575
48 0.1584 16 2.5344
uJ 52.0641
So 52uJ per transmit?   How many uJ do we have in our battery?

//Mik
Pins 9 and 10 on the DWM are used to determine the phase and polarity of the SPI signal.  Getting these two things set right, the bit-rate and the the bit direction (lsig, or msig bit sent first) has always been a PITA invlving poring over the scope for hours.  

The Aardvark is probably a better way to suss these things out rather than writing trial-and-error programs for the Nordic.  I found the Aardvark confusing and wasn't making progress, so I lashed out $20 and bought a Bus Pirate which is easier to understand, and all the software is open source.  As you can see from the blog, I managed to get some sense out of it, so I'm flushed with over confidence.
So here's the question, I was thinking of connecting the Bus Pirate directly to the DW module.  But I'm not sure if there will be conflicts with the power somehow.  The BP itself can supply 3.3V and 5V, so maybe I don't have to even plug the TS06 into it's PSU.   Alternatively I can just connect it to the 4 SPI signals and GND, and use the USB PSU for the TS06.  Pls advise.

//Mik

I got a simple loop-back SPI program to work.  I connected MISO to MISO with a jumper and then checked to see that the characters I sent out on MOSI matched the ones I got back on MISO.

It appears to be important to to set the slave select high before configuring it as an output or it creates glitches.

MISO is configured with no pullup.

The Nordic has two SPI channels which can be pointed at any set of GPIOs.

p_nrf_spi->PSELSCK  = p_spi_master_config->SPI_Pin_SCK;
p_nrf_spi->PSELMOSI = p_spi_master_config->SPI_Pin_MOSI;
p_nrf_spi->PSELMISO = p_spi_master_config->SPI_Pin_MISO;

I initialised the code to run with:

POL=ActiveHigh; 
PHA=Leading;
FREQ=125Kb;
BITORDER=MsbFirst

This is right for BusPirate SPI_Sniffer, but the bits are back-to-front on the scope

My program sets up to catch interrupts, and the interrupt handler simply sets a flag when the IO has finished.  The main loop

Here’s some output.

0: Hello SPI! => Hello SPI!
1: Hello SPI! => Hello SPI!
2: Hello SPI! => Hello SPI!
3: Hello SPI! => Hello SPI!
4: Hello SPI! => Hello SPI!
5: Hello SPI! => Hello SPI!
6: Hello SPI! => Hello SPI!
7: Hello SPI! => Hello SPI!
8: Hello SPI! => Hello SPI!
9: Hello SPI! => Hel

If the jumper is not in place then the SPI hardware clocks character 255 into the receive buffer.

0: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
1: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
2: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
3: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
4: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
5: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
6: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
7: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
8: Hello SPI! => ÿÿÿÿÿÿÿÿÿÿ
9: Hello SPI! => ÿÿÿÿÿÿÿÿ

Using the Bus Pirate and SPI_Sniffer

The startup bat file contain this:

SPIsniffer -d COM4 -r 0 -s 125000
pause

The data is interpreted as follows:

BP_record ::= CS_low ‘[‘ { DataPair } CS_hi ‘]’ 

CS_low    ::= 0x5B
CS_hi     ::= 0x5D
DataPair  ::= MOSI ‘(‘ MISO ‘)’
 

MOSI      ::= .dec .hex
MISO      ::= .dec .hex

SPI working on TS06.2

I connected Noridc pin20 to pin22 to create the SPI loopback.
It worked right away!  Yay.
Discovered that the LED on pin0 is not working.

I needed to learn how to do interrupt handling on the Nordic.  The simplest thing seemed to be to setup the RTC to generate regular interrupts.  It was a useful process because I learned quite a bit about the hardware in the process.

(My test program is called: RTC_C_nRF51822)
There are two clocks: a low-frequency clock, and a high-frequency clock.  The LFCLK runs at 32KHz.  It generates the basic system tick which is a sub-multiple of the 32768Hz.  The PRESCALAR which essentially divides the clock is only 12 bits wide, so the slowest clock-tick is 32768/(0xFFF + 1) = 8Hz.

#define RTC_FREQUENCY_HZ  (10UL) 
#define COUNTER_PRESCALER ((LFCLK_FREQUENCY / RTC_FREQUENCY_HZ) – 1)

The name of the interrupt routine is hard-wired : void RTC0_IRQHandler()  It gets called at RTC_FREQUENCY_HZ.

There is another times called the “compare” timer that can be set to cause an timer interrupt at any multiple of RTC_FREQUENCY_HZ.

Whereas the basic tick interrupt repeats automatically, the compare timer is a one-shot and has to be restarted.

So the basic process involves setting up the timer frequencies, and the interrupt events and masks, and then going to sleep until a tick, or “compare” interrupt occurs.

The sleep loop is a little subtle.  It is important to make sure that all pending interrupts are processed before sleeping, for which this opaque/confusing sequence is recommended.

// Enter System ON sleep mode __WFE(); // Make sure any pending events are cleared __SEV(); __WFE();

Incidentally I learned that the basic printf procedure is interrupts driven, so it get’s a bit confusing.

So here’s an example that toggles one LED every ten system ticks, and the other at 3Hz.

I noticed that in sleep mode the board is still consuming about 1.5mA with the LEDs off.