From 0fa841036f516d73afc861e793448877c3df1883 Mon Sep 17 00:00:00 2001
From: Henk Muller <henk@xmos.com>
Date: Fri, 20 Oct 2017 12:07:10 +0100
Subject: [PATCH 01/10] First effort at extracting true random bits - horribly
 broken at the moment

---
 .../AN002xx_random_number_generation/Makefile | 10 ++++
 .../README.rst                                | 34 ++++++++++++
 .../config.xscope                             | 23 ++++++++
 .../doc/rst/AN002xx.rst                       | 11 ++++
 .../doc/rst/xdoc.conf                         |  2 +
 .../src/random_numbers.xc                     | 25 +++++++++
 lib_random/api/random.h                       | 13 +++++
 lib_random/src/true_random.xc                 | 53 +++++++++++++++++++
 8 files changed, 171 insertions(+)
 create mode 100644 examples/AN002xx_random_number_generation/Makefile
 create mode 100644 examples/AN002xx_random_number_generation/README.rst
 create mode 100644 examples/AN002xx_random_number_generation/config.xscope
 create mode 100644 examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst
 create mode 100644 examples/AN002xx_random_number_generation/doc/rst/xdoc.conf
 create mode 100644 examples/AN002xx_random_number_generation/src/random_numbers.xc
 create mode 100644 lib_random/src/true_random.xc

diff --git a/examples/AN002xx_random_number_generation/Makefile b/examples/AN002xx_random_number_generation/Makefile
new file mode 100644
index 0000000..504dbff
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/Makefile
@@ -0,0 +1,10 @@
+TARGET = SMART-MIC-4-TILE-1V0
+APP_NAME =
+USED_MODULES = lib_random
+
+XCC_FLAGS = -O2 -g -fxscope -Wunused
+XCORE_ARM_PROJECT = 0
+VERBOSE = 0
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/examples/AN002xx_random_number_generation/README.rst b/examples/AN002xx_random_number_generation/README.rst
new file mode 100644
index 0000000..a92471e
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/README.rst
@@ -0,0 +1,34 @@
+Noise Suppression and Automatic Gain Control example
+====================================================
+
+.. version:: 0.0.1
+
+Summary
+-------
+
+This example demonstrates how to use the automatic gain control library,
+the noise suppression library, and the microphone array library in order to
+create a meaningful AGC
+
+Required tools and libraries
+............................
+
+.. appdeps::
+
+Required hardware
+.................
+
+A smart microphone board.
+
+Prerequisites
+.............
+
+ * This document assumes familiarity with the XMOS xCORE architecture,
+   the XMOS tool chain and the xC language. Documentation related to these
+   aspects which are not specific to this application note are linked to in
+   the references appendix.
+  
+ * For a description of XMOS related terms found in this document
+   please see the XMOS Glossary [#]_.
+
+.. [#] http://www.xmos.com/published/glossary
diff --git a/examples/AN002xx_random_number_generation/config.xscope b/examples/AN002xx_random_number_generation/config.xscope
new file mode 100644
index 0000000..6436587
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/config.xscope
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- ======================================================= -->
+<!-- The 'ioMode' attribute on the xSCOPEconfig              -->
+<!-- element can take the following values:                  -->
+<!--   "none", "basic", "timed"                              -->
+<!--                                                         -->
+<!-- The 'type' attribute on Probe                           -->
+<!-- elements can take the following values:                 -->
+<!--   "STARTSTOP", "CONTINUOUS", "DISCRETE", "STATEMACHINE" -->
+<!--                                                         -->
+<!-- The 'datatype' attribute on Probe                       -->
+<!-- elements can take the following values:                 -->
+<!--   "NONE", "UINT", "INT", "FLOAT"                        -->
+<!-- ======================================================= -->
+
+<xSCOPEconfig ioMode="basic" enabled="false">
+
+    <!-- For example: -->
+    <Probe name="CH0" type="CONTINUOUS" datatype="INT" units="Value" enabled="true"/>
+    <!-- From the target code, call: xscope_int(PROBE_NAME, value); -->
+
+</xSCOPEconfig>
diff --git a/examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst b/examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst
new file mode 100644
index 0000000..08592a2
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst
@@ -0,0 +1,11 @@
+.. include:: ../../README.rst
+
+|newpage|
+
+Overview
+--------
+
+Introduction
+............
+
+This demo application shows how to use random numbers.
diff --git a/examples/AN002xx_random_number_generation/doc/rst/xdoc.conf b/examples/AN002xx_random_number_generation/doc/rst/xdoc.conf
new file mode 100644
index 0000000..cb5aab6
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/doc/rst/xdoc.conf
@@ -0,0 +1,2 @@
+XMOSNEWSTYLE=1
+SOURCE_INCLUDE_DIRS=../../src
diff --git a/examples/AN002xx_random_number_generation/src/random_numbers.xc b/examples/AN002xx_random_number_generation/src/random_numbers.xc
new file mode 100644
index 0000000..eb804e2
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/src/random_numbers.xc
@@ -0,0 +1,25 @@
+// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
+
+#include <stdint.h>
+#include <stdio.h>
+#include <xs1.h>
+#include "random.h"
+
+#define N 32
+
+int main(void) {
+    int n[N], rand[N];
+    timer tmr;
+    int t0;
+    printf("Hello\n");
+    random_true_init();
+    for(int i = 0; i < N; i++) {
+        tmr :> t0;
+        tmr when timerafter(t0 + 10000) :> void;
+        {n[i], rand[i]} = random_true_get_bits();
+    }
+    for(int i = 0; i < N; i++) {
+        printf("** %d %d\n", n[i], rand[i]);
+    }
+    return 0;
+}
diff --git a/lib_random/api/random.h b/lib_random/api/random.h
index 72efee2..de79329 100644
--- a/lib_random/api/random.h
+++ b/lib_random/api/random.h
@@ -47,4 +47,17 @@ random_get_random_number(REFERENCE_PARAM(random_generator_t, g));
 
 void random_get_random_bytes(REFERENCE_PARAM(random_generator_t, g), uint8_t in_buffer[], size_t byte_count);
 
+#ifdef __XC__
+/** Function that produces a number of random bits. It returns two
+ * integers, the number of random bits, and the actual random bits. At most
+ * 16 random bits are returned. To get a large number of random bits this
+ * function should be called regularly. Calling it too quickly since a
+ * previous call will return 0.
+ *
+ * \returns Number of bits, and random bits.
+ */
+{uint32_t,uint32_t} random_true_get_bits();
+void random_true_init();
+#endif
+
 #endif // __RANDOM_H__
diff --git a/lib_random/src/true_random.xc b/lib_random/src/true_random.xc
new file mode 100644
index 0000000..5a37b19
--- /dev/null
+++ b/lib_random/src/true_random.xc
@@ -0,0 +1,53 @@
+#include <platform.h>
+#include <stdio.h>
+#include <xs1.h>
+#include <xclib.h>
+#include "random.h"
+
+#define MIN_RANDOM_BITS 8
+
+{int,int} static getro() {
+    int time;
+    asm("gettime %0" : "=r" (time));
+    setps(0x60B, 0);
+    short x = getps(0x70B);
+    setps(0x60B, 3);
+    return {time, x};
+}
+
+static int last_used_time, last_used_ro;
+static unsigned current_ro_per_tick;
+
+void random_true_init() {
+    int time, ro, time2, ro2;
+    timer tmr;
+    {time, ro} = getro();
+    tmr when timerafter(time+1000) :> void;
+    {time2, ro2} = getro();
+    last_used_time = time;
+    last_used_ro = ro;
+    current_ro_per_tick = (ro2 - last_used_ro) * 0x10000LL / (time2 - last_used_time);
+//    printf("%9u %5u %08x\n", last_used_time, last_used_ro & 0xFFFFU, current_ro_per_tick);
+}
+
+static inline int cls(int x) {
+    return x < 0 ? clz(-x) : clz(x);
+}
+
+{uint32_t,uint32_t} random_true_get_bits() {
+    int time, ro;
+    {time, ro} = getro();
+    int dtime = time - last_used_time;
+    short expectedro = last_used_ro + ((dtime * (long long) current_ro_per_tick) >> 16);
+    short dro = ro - expectedro;
+    int random_bits = dro >> MIN_RANDOM_BITS;
+    int nbits = 31 - cls(random_bits);
+    if (nbits > 0) {
+        current_ro_per_tick = (expectedro + dro - last_used_ro) * 0x10000LL / (time - last_used_time);
+        last_used_time = time;
+        last_used_ro = ro;
+        printf("%9u %5u %08x\n", last_used_time, last_used_ro & 0xFFFFU, current_ro_per_tick);
+        return {nbits, dro & (1 << nbits) - 1};
+    }
+    return {0, 0};
+}

From 1bab77672a844739574db5dc3219274e9aa7b1e0 Mon Sep 17 00:00:00 2001
From: Henk Muller <henk@xmos.com>
Date: Mon, 23 Oct 2017 16:55:21 +0100
Subject: [PATCH 02/10] First version of true random that does something that
 appears alrightish

---
 .../AN002xx_random_number_generation/Makefile |   2 +-
 .../src/random_numbers.xc                     | 111 ++++++++++++++++--
 lib_random/src/true_random.xc                 |  38 +++---
 3 files changed, 126 insertions(+), 25 deletions(-)

diff --git a/examples/AN002xx_random_number_generation/Makefile b/examples/AN002xx_random_number_generation/Makefile
index 504dbff..48cf165 100644
--- a/examples/AN002xx_random_number_generation/Makefile
+++ b/examples/AN002xx_random_number_generation/Makefile
@@ -2,7 +2,7 @@ TARGET = SMART-MIC-4-TILE-1V0
 APP_NAME =
 USED_MODULES = lib_random
 
-XCC_FLAGS = -O2 -g -fxscope -Wunused
+XCC_FLAGS = -O2 -g -Wunused -fxscope
 XCORE_ARM_PROJECT = 0
 VERBOSE = 0
 
diff --git a/examples/AN002xx_random_number_generation/src/random_numbers.xc b/examples/AN002xx_random_number_generation/src/random_numbers.xc
index eb804e2..93082b5 100644
--- a/examples/AN002xx_random_number_generation/src/random_numbers.xc
+++ b/examples/AN002xx_random_number_generation/src/random_numbers.xc
@@ -2,24 +2,115 @@
 
 #include <stdint.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <xs1.h>
 #include "random.h"
 
-#define N 32
+#define MAXX 256
+#define MAXY 256
+#define MAXBITS (MAXX * MAXY)
 
-int main(void) {
-    int n[N], rand[N];
+unsigned char bits[MAXBITS];
+
+void blocktest(int n) {
+    int hist[256];
+    for(int i = 0; i < 256; i++) {
+        hist[i] = 0;
+    }
+    for(int i = 0; i < MAXBITS - n; i++) {
+        int val = 0;
+        for(int j = 0; j < n; j++) {
+            val = val << 1 | bits[i+j];
+        }
+        hist[val]++;
+    }
+    printf("Blocktest %d\n", n);
+    for(int i = 0; i < (1<<n); i++) {
+        printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i]-(MAXBITS >> n)) < MAXX ? "Ok" : "Hmm");
+    }
+    printf("\n");
+}
+
+void runtest() {
+    int hist[200];
+    int old = 0;
+    int run = 0;
+    for(int i = 0; i < 200; i++) {
+        hist[i] = 0;
+    }
+    for(int i = 0; i < MAXBITS; i++) {
+        if(bits[i] == old) {
+            run++;
+        } else {
+            hist[run]++;
+            run = 1;
+        }
+    }
+    printf("Runtest:\n");
+    for(int i = 1; i < 10; i++) {
+        printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i] - (MAXBITS >> (i+1))) < (MAXX >> (i/2)) ? "Ok" : "Hmm" );
+    }
+    printf("\n");
+}
+
+void xmain(void) {
+    int n, rand;
     timer tmr;
     int t0;
-    printf("Hello\n");
+    int sum = 0;
+    int ns = 0;
+    int ticks = 1500;
     random_true_init();
-    for(int i = 0; i < N; i++) {
-        tmr :> t0;
-        tmr when timerafter(t0 + 10000) :> void;
-        {n[i], rand[i]} = random_true_get_bits();
+    while(sum < MAXBITS) {
+//        tmr when timerafter(t0 + ticks) :> void;
+        {n, rand} = random_true_get_bits();
+        if (n == 0) {
+            tmr :> t0;
+            tmr when timerafter(t0 + 10 + 0 * rand) :> void;
+        } else {
+            for(int i = 0; i < n && sum < MAXBITS; i++) {
+                bits[sum] = rand & 1;
+                rand >>= 1;
+                sum++;
+            }
+            ns++;
+        }
+    }
+    printf("Average bits per call %f at %d ticks\n", sum/(float)ns, ticks);
+    blocktest(1);
+    blocktest(2);
+    blocktest(3);
+    runtest();
+//    printf("P2\n%d %d\n1\n", MAXX, MAXY);
+    for(int i = 0; i < MAXX; i++) {
+        for(int j = 0; j < MAXY; j++) {
+//            printf("%d ", bits[i*MAXY+j]);
+        }
+//        printf("\n");
+    }
+}
+
+int busy(int x) {
+    return 0;
+    for(int j = 0; j < 100; j++) {
+        for(int i = 0; i < 100000000; i++) {
+            x = x * 1234567 + 1;
+        }
     }
-    for(int i = 0; i < N; i++) {
-        printf("** %d %d\n", n[i], rand[i]);
+    printf("%d\n", x);
+    return x;
+}
+
+int main(void) {
+    par {
+        busy(0x3);
+        busy(0x4);
+        busy(0x5);
+        busy(0x6);
+        busy(0x7);
+        busy(0x8);
+        busy(0x9);
+        xmain();
     }
     return 0;
 }
diff --git a/lib_random/src/true_random.xc b/lib_random/src/true_random.xc
index 5a37b19..3b6de2b 100644
--- a/lib_random/src/true_random.xc
+++ b/lib_random/src/true_random.xc
@@ -4,30 +4,36 @@
 #include <xclib.h>
 #include "random.h"
 
-#define MIN_RANDOM_BITS 8
+#define MIN_RANDOM_BITS 12
 
 {int,int} static getro() {
     int time;
-    asm("gettime %0" : "=r" (time));
     setps(0x60B, 0);
+    asm("nop");
+    asm("nop");
+    asm("nop");
+    asm("nop");
     short x = getps(0x70B);
+    asm("gettime %0" : "=r" (time));
     setps(0x60B, 3);
     return {time, x};
 }
 
 static int last_used_time, last_used_ro;
 static unsigned current_ro_per_tick;
+static int scanning = 0;
+static int final_time = 0;
 
 void random_true_init() {
     int time, ro, time2, ro2;
     timer tmr;
     {time, ro} = getro();
-    tmr when timerafter(time+1000) :> void;
+    tmr when timerafter(time+5000) :> void;
     {time2, ro2} = getro();
     last_used_time = time;
     last_used_ro = ro;
-    current_ro_per_tick = (ro2 - last_used_ro) * 0x10000LL / (time2 - last_used_time);
-//    printf("%9u %5u %08x\n", last_used_time, last_used_ro & 0xFFFFU, current_ro_per_tick);
+    current_ro_per_tick = ((short)(ro2 - last_used_ro)) * 0x10000LL / (time2 - last_used_time);
+    scanning = 1;
 }
 
 static inline int cls(int x) {
@@ -37,17 +43,21 @@ static inline int cls(int x) {
 {uint32_t,uint32_t} random_true_get_bits() {
     int time, ro;
     {time, ro} = getro();
+    
     int dtime = time - last_used_time;
-    short expectedro = last_used_ro + ((dtime * (long long) current_ro_per_tick) >> 16);
+    int expectedro = last_used_ro + ((dtime * (long long) current_ro_per_tick) >> 16);
     short dro = ro - expectedro;
-    int random_bits = dro >> MIN_RANDOM_BITS;
-    int nbits = 31 - cls(random_bits);
-    if (nbits > 0) {
-        current_ro_per_tick = (expectedro + dro - last_used_ro) * 0x10000LL / (time - last_used_time);
-        last_used_time = time;
-        last_used_ro = ro;
-        printf("%9u %5u %08x\n", last_used_time, last_used_ro & 0xFFFFU, current_ro_per_tick);
+    int nbits = 32 - cls(dro) - MIN_RANDOM_BITS;
+    if (scanning) {    
+        if (nbits <= 0) {
+            return {0, 10000};    // called much too early
+        }
+        final_time = time + dtime;
+        scanning = 0;
+        return {0, dtime};    // call again in dtime;
+    } else if ((time - final_time) > 0) {
+        random_true_init();
         return {nbits, dro & (1 << nbits) - 1};
     }
-    return {0, 0};
+    return {0,final_time - time};
 }

From 07c4ed0d73956951c345976bc809668134841d48 Mon Sep 17 00:00:00 2001
From: Henk Muller <henk@xmos.com>
Date: Mon, 23 Oct 2017 16:59:54 +0100
Subject: [PATCH 03/10] First version of true random that does something that
 appears alrightish

---
 .../src/random_numbers.xc                        | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/examples/AN002xx_random_number_generation/src/random_numbers.xc b/examples/AN002xx_random_number_generation/src/random_numbers.xc
index 93082b5..4576973 100644
--- a/examples/AN002xx_random_number_generation/src/random_numbers.xc
+++ b/examples/AN002xx_random_number_generation/src/random_numbers.xc
@@ -10,7 +10,15 @@
 #define MAXY 256
 #define MAXBITS (MAXX * MAXY)
 
-unsigned char bits[MAXBITS];
+unsigned char thebits[MAXBITS/8];
+
+unsigned int getbit(int i) {
+    return (thebits[i>>3] >> (i&7)) & 1;
+}
+
+unsigned int setbit(int i) {
+    return thebits[i>>3] |= 1 << (i&7);
+}
 
 void blocktest(int n) {
     int hist[256];
@@ -20,7 +28,7 @@ void blocktest(int n) {
     for(int i = 0; i < MAXBITS - n; i++) {
         int val = 0;
         for(int j = 0; j < n; j++) {
-            val = val << 1 | bits[i+j];
+            val = val << 1 | getbit(i+j);
         }
         hist[val]++;
     }
@@ -39,7 +47,7 @@ void runtest() {
         hist[i] = 0;
     }
     for(int i = 0; i < MAXBITS; i++) {
-        if(bits[i] == old) {
+        if(getbit(i) == old) {
             run++;
         } else {
             hist[run]++;
@@ -69,7 +77,7 @@ void xmain(void) {
             tmr when timerafter(t0 + 10 + 0 * rand) :> void;
         } else {
             for(int i = 0; i < n && sum < MAXBITS; i++) {
-                bits[sum] = rand & 1;
+                setbit(sum, rand & 1);
                 rand >>= 1;
                 sum++;
             }

From 4307eefe431de0ecaa530a1968c3b82b412f6cb4 Mon Sep 17 00:00:00 2001
From: Henk Muller <henk@xmos.com>
Date: Wed, 1 Nov 2017 12:11:28 +0000
Subject: [PATCH 04/10] TOok all the clever bits out as they reduced
 randomness. Left with a simple implementation that will produce random if the
 attacker does not have physical access to the chip

---
 .../src/random_numbers.xc                     | 86 ++++++++++++-------
 lib_random/api/random.h                       | 31 +++++--
 lib_random/src/true_random.xc                 | 75 +++++++---------
 3 files changed, 112 insertions(+), 80 deletions(-)

diff --git a/examples/AN002xx_random_number_generation/src/random_numbers.xc b/examples/AN002xx_random_number_generation/src/random_numbers.xc
index 4576973..e369c94 100644
--- a/examples/AN002xx_random_number_generation/src/random_numbers.xc
+++ b/examples/AN002xx_random_number_generation/src/random_numbers.xc
@@ -6,8 +6,8 @@
 #include <xs1.h>
 #include "random.h"
 
-#define MAXX 256
-#define MAXY 256
+#define MAXX 1024
+#define MAXY 1024
 #define MAXBITS (MAXX * MAXY)
 
 unsigned char thebits[MAXBITS/8];
@@ -16,8 +16,8 @@ unsigned int getbit(int i) {
     return (thebits[i>>3] >> (i&7)) & 1;
 }
 
-unsigned int setbit(int i) {
-    return thebits[i>>3] |= 1 << (i&7);
+unsigned int setbit(int i, int val) {
+    return thebits[i>>3] |= val << (i&7);
 }
 
 void blocktest(int n) {
@@ -61,64 +61,92 @@ void runtest() {
     printf("\n");
 }
 
-void xmain(void) {
+void fillmepseudo(void) {
+    random_generator_t rt = random_create_generator_from_seed(0);
+    int sum = 0;
+    random_true_init();
+    while(sum < MAXBITS) {
+        unsigned rand = random_get_random_number(rt);
+        for(int i = 0; i < 32 && sum < MAXBITS; i++) {
+            setbit(sum, rand & 1);
+            rand >>= 1;
+            sum++;
+        }
+    }
+}
+
+void fillmetrue(void) {
     int n, rand;
     timer tmr;
-    int t0;
+    int t0, t1;
     int sum = 0;
-    int ns = 0;
-    int ticks = 1500;
     random_true_init();
+    tmr :> t0;
     while(sum < MAXBITS) {
-//        tmr when timerafter(t0 + ticks) :> void;
         {n, rand} = random_true_get_bits();
         if (n == 0) {
-            tmr :> t0;
-            tmr when timerafter(t0 + 10 + 0 * rand) :> void;
+           // tmr when timerafter(rand) :> void;
         } else {
             for(int i = 0; i < n && sum < MAXBITS; i++) {
                 setbit(sum, rand & 1);
                 rand >>= 1;
                 sum++;
             }
-            ns++;
+            if ((sum & 0xffff) == 0) {
+                int time;
+                asm volatile ("gettime %0" : "=r" (time));
+                printf("%11d %d\n", time, sum);
+            }
         }
     }
-    printf("Average bits per call %f at %d ticks\n", sum/(float)ns, ticks);
+    tmr :> t1;
+    printf("Ticks taken: %d, %d per bit\n", t1-t0, (t1-t0)/sum);
+}
+
+void xmain(chanend done[7]) {
+    for(int i = 0; i < 7; i++) {
+        done[i] <: 0;
+    }
+    fillmetrue();
     blocktest(1);
     blocktest(2);
     blocktest(3);
     runtest();
-//    printf("P2\n%d %d\n1\n", MAXX, MAXY);
+    return;
+    printf("P2\n%d %d\n1\n", MAXX, MAXY);
     for(int i = 0; i < MAXX; i++) {
         for(int j = 0; j < MAXY; j++) {
-//            printf("%d ", bits[i*MAXY+j]);
+            printf("%d ", getbit(i*MAXY+j));
         }
-//        printf("\n");
+        printf("\n");
     }
 }
 
-int busy(int x) {
-    return 0;
-    for(int j = 0; j < 100; j++) {
-        for(int i = 0; i < 100000000; i++) {
+int busy(int x, chanend y) {
+    while(1) {
+        for(int i = 0; i < 1000; i++) {
             x = x * 1234567 + 1;
         }
+        select {
+            case y :> int _: return x;
+            default:  break;
+        }
     }
-    printf("%d\n", x);
     return x;
 }
 
+
 int main(void) {
+    chan done[7];
     par {
-        busy(0x3);
-        busy(0x4);
-        busy(0x5);
-        busy(0x6);
-        busy(0x7);
-        busy(0x8);
-        busy(0x9);
-        xmain();
+        busy(0x3, done[0]);
+        busy(0x4, done[1]);
+        busy(0x5, done[2]);
+        busy(0x6, done[3]);
+        busy(0x7, done[4]);
+        busy(0x8, done[5]);
+        busy(0x9, done[6]);
+        xmain(done);
     }
     return 0;
 }
diff --git a/lib_random/api/random.h b/lib_random/api/random.h
index de79329..5a506fc 100644
--- a/lib_random/api/random.h
+++ b/lib_random/api/random.h
@@ -49,15 +49,34 @@ void random_get_random_bytes(REFERENCE_PARAM(random_generator_t, g), uint8_t in_
 
 #ifdef __XC__
 /** Function that produces a number of random bits. It returns two
- * integers, the number of random bits, and the actual random bits. At most
- * 16 random bits are returned. To get a large number of random bits this
- * function should be called regularly. Calling it too quickly since a
- * previous call will return 0.
+ * integers.
  *
- * \returns Number of bits, and random bits.
+ * If random bits are available, then it returns the number of random bits,
+ * and the actual random bits.
+ *
+ * If no random bits are available, then it returns 0 (for no random bits)
+ * and the time in ticks at which new bits are available. The code can wait
+ * for this time (for example in a select statement), and then collect the
+ * random bits.
+ * 
+ * At most 16 random bits are returned. To get a large number of random
+ * bits this function should be called regularly. Calling it too quickly
+ * since a previous call will return 0.
+ *
+ * \returns Number of bits, and random bits, or 0 and timestamp in the future.
+ */
+{uint32_t,int32_t} random_true_get_bits();
+
+/** Function that initialises the true random number generator. Calling
+ * this function will start the free running oscillator. This will take a
+ * bit of extra power.
  */
-{uint32_t,uint32_t} random_true_get_bits();
 void random_true_init();
+
+/** Function that uninitialises the true random number generator. This will
+ * stop the ring oscillator, and reduce the power foot print a little.
+ */
+void random_true_uninit();
 #endif
 
 #endif // __RANDOM_H__
diff --git a/lib_random/src/true_random.xc b/lib_random/src/true_random.xc
index 3b6de2b..7dbc852 100644
--- a/lib_random/src/true_random.xc
+++ b/lib_random/src/true_random.xc
@@ -4,60 +4,45 @@
 #include <xclib.h>
 #include "random.h"
 
-#define MIN_RANDOM_BITS 12
+#define MIN_RANDOM_BITS 8
 
-{int,int} static getro() {
-    int time;
+static void inline ro_on() {
+    setps(0x60B, 2);
+}
+
+static void inline ro_off() {
     setps(0x60B, 0);
-    asm("nop");
-    asm("nop");
-    asm("nop");
-    asm("nop");
-    short x = getps(0x70B);
-    asm("gettime %0" : "=r" (time));
-    setps(0x60B, 3);
-    return {time, x};
 }
 
-static int last_used_time, last_used_ro;
-static unsigned current_ro_per_tick;
-static int scanning = 0;
-static int final_time = 0;
 
-void random_true_init() {
-    int time, ro, time2, ro2;
-    timer tmr;
-    {time, ro} = getro();
-    tmr when timerafter(time+5000) :> void;
-    {time2, ro2} = getro();
-    last_used_time = time;
-    last_used_ro = ro;
-    current_ro_per_tick = ((short)(ro2 - last_used_ro)) * 0x10000LL / (time2 - last_used_time);
-    scanning = 1;
-}
 
-static inline int cls(int x) {
-    return x < 0 ? clz(-x) : clz(x);
+#define TIME_FOR_ONE_BIT 20000
+static int last_time = 0;
+
+void random_true_init() {
+    asm("gettime %0" : "=r" (last_time));
+    ro_on();
 }
 
-{uint32_t,uint32_t} random_true_get_bits() {
+{uint32_t,int32_t} random_true_get_bits() {
     int time, ro;
-    {time, ro} = getro();
+
+    ro_off();
+    asm("nop");
+    asm("nop");
+    asm("nop");
+    asm("nop");
+    ro = getps(0x70B);
+    asm("gettime %0" : "=r" (time));
+    ro_on();
     
-    int dtime = time - last_used_time;
-    int expectedro = last_used_ro + ((dtime * (long long) current_ro_per_tick) >> 16);
-    short dro = ro - expectedro;
-    int nbits = 32 - cls(dro) - MIN_RANDOM_BITS;
-    if (scanning) {    
-        if (nbits <= 0) {
-            return {0, 10000};    // called much too early
-        }
-        final_time = time + dtime;
-        scanning = 0;
-        return {0, dtime};    // call again in dtime;
-    } else if ((time - final_time) > 0) {
-        random_true_init();
-        return {nbits, dro & (1 << nbits) - 1};
+    if (((unsigned)(time - last_time)) > TIME_FOR_ONE_BIT) {
+        last_time = time;
+        return {1, ro & 1};
     }
-    return {0,final_time - time};
+    return {0, last_time + TIME_FOR_ONE_BIT};
+}
+
+void random_true_uninit() {
+    ro_off();
 }

From 456de3823d0cc844c6b3b52215769420040b6a17 Mon Sep 17 00:00:00 2001
From: Henk Muller <henk@xmos.com>
Date: Wed, 1 Nov 2017 12:12:13 +0000
Subject: [PATCH 05/10] Added board file on which random number generator was
 developed - should probably be removed and replaced with ordinary
 EXPLORER-200.

---
 .../SMART-MIC-4-TILE-1V0.xn                   | 153 ++++++++++++++++++
 1 file changed, 153 insertions(+)
 create mode 100755 examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn

diff --git a/examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn b/examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn
new file mode 100755
index 0000000..1bb07e9
--- /dev/null
+++ b/examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Network xmlns="http://www.xmos.com"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
+  <Type>Device</Type>
+  <Name>Mic Array Quad Tile</Name>
+
+  <Declarations>
+    <Declaration>tileref tile[4]</Declaration>
+    <Declaration>tileref usb_tile</Declaration>
+  </Declarations>
+
+  <Packages>
+    <Package id="0" Type="XS2-UFnA-512-TQ128">
+      <Nodes>
+          <Node Id="0" InPackageId="0" Type="XS2-L16A-512" Oscillator="24MHz" SystemFrequency="500MHz" ReferenceFrequency="100MHz">
+
+          <Boot>
+            <Source Location="bootFlash0"/>
+            <Bootee NodeId="2"/>
+          </Boot>
+          <Tile Number="0" Reference="tile[0]">
+            <!-- Quad flash ports -->
+            <Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
+            <Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
+            <Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
+
+            <Port Location="XS1_PORT_1M" Name="PORT_PLL_MOD"/>
+            <Port Location="XS1_PORT_1P" Name="PORT_BGT_SPI_CLK"/>
+            <Port Location="XS1_PORT_1A" Name="PORT_BGT_SPI_CS_N"/>
+            <Port Location="XS1_PORT_1F" Name="PORT_BGT_SPI_MISO"/>
+            <Port Location="XS1_PORT_1E" Name="PORT_BGT_SPI_MOSI"/>
+            <Port Location="XS1_PORT_1D" Name="PORT_BGT_IRQ"/>
+            <Port Location="XS1_PORT_1O" Name="PORT_I2C_SCL"/>
+            <Port Location="XS1_PORT_1N" Name="PORT_I2C_SDA"/>
+          </Tile>
+          <Tile Number="1" Reference="tile[1]">
+            <!-- USB -->
+            <Port Location="XS1_PORT_1H"  Name="PORT_USB_TX_READYIN"/>
+            <Port Location="XS1_PORT_1J"  Name="PORT_USB_CLK"/>
+            <Port Location="XS1_PORT_1K"  Name="PORT_USB_TX_READYOUT"/>
+            <Port Location="XS1_PORT_1I"  Name="PORT_USB_RX_READY"/>
+            <Port Location="XS1_PORT_1E"  Name="PORT_USB_FLAG0"/>
+            <Port Location="XS1_PORT_1F"  Name="PORT_USB_FLAG1"/>
+            <Port Location="XS1_PORT_1G"  Name="PORT_USB_FLAG2"/>
+            <Port Location="XS1_PORT_8A"  Name="PORT_USB_TXD"/>
+            <Port Location="XS1_PORT_8B"  Name="PORT_USB_RXD"/>
+
+            <!-- I2C -->
+            <!-- Note: Bit 1 of PORT 4E is I2C_SCL -->
+            <!--       Bit 2 of PORT 4E is I2C_SDA -->
+            <Port Location="XS1_PORT_4E" Name="PORT_I2C_SCL_SDA"/>
+            <Port Location="XS1_PORT_4F" Name="PORT_DAC_RST_N"/>
+
+            <!-- I2S -->
+            <Port Location="XS1_PORT_1M" Name="PORT_I2S_BCLK"/>
+            <Port Location="XS1_PORT_1N" Name="PORT_I2S_LRCLK"/>
+            <Port Location="XS1_PORT_1O" Name="PORT_MCLK_IN"/>
+            <Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC0"/>
+            <Port Location="XS1_PORT_1L" Name="PORT_I2S_DAC1"/>
+            <Port Location="XS1_PORT_1C"  Name="PORT_I2S_ADC0"/>
+            <Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
+          </Tile>
+        </Node>
+        <Node Id="1" InPackageId="1" Type="periph:XS1-SU" Reference="usb_tile" Oscillator="24MHz"/>
+      </Nodes>
+      <Links>
+        <Link Encoding="5wire">
+          <LinkEndpoint NodeId="0" Link="8" Delays="52clk,52clk"/>
+          <LinkEndpoint NodeId="1" Link="XL0" Delays="1clk,1clk"/>
+        </Link>
+      </Links>
+    </Package>
+
+    <Package id="1" Type="XS2-LnA-512-TQ128">
+      <Nodes>
+        <Node Id="2" InPackageId="0" Type="XS2-L16A-512" SystemFrequency="500MHz" Oscillator="24MHz" ReferenceFrequency="100MHz">
+          <Boot>
+            <Source Location="LINK" BootMode="4"/>
+          </Boot>
+          <Tile Number="0" Reference="tile[2]">
+            <!-- Mics -->
+            <!-- Notes: XS1_PORT_4C is for mics 0, 1, 6 and 7 -->
+            <!--        XS1_PORT_4D is for mics 2, 3, 4 and 5 -->
+            <Port Location="XS1_PORT_8B" Name="PORT_PDM_DATA"/>
+            <Port Location="XS1_PORT_1G" Name="PORT_PDM_MCLK"/>
+            <Port Location="XS1_PORT_1H" Name="PORT_PDM_CLK"/>
+          </Tile>
+          <Tile Number="1" Reference="tile[3]">
+            <!-- Wireless LAN -->
+            <Port Location="XS1_PORT_1A" Name="PORT_WLAN_SPI_MOSI"/>
+            <Port Location="XS1_PORT_1B" Name="PORT_WLAN_SPI_MISO"/>
+            <Port Location="XS1_PORT_4A" Name="PORT_WLAN_WLAN_SPI_IRQ_N"/>
+            <!-- Note: Bit 1 of PORT 4B is WLAN_3V3_EN -->
+            <!--       Bit 2 of PORT 4B is WLAN_RST_N  -->
+            <Port Location="XS1_PORT_4B" Name="PORT_WLAN_3V3_EN_RST_N"/>
+            <Port Location="XS1_PORT_1C" Name="PORT_WLAN_SPI_CLK"/>
+            <Port Location="XS1_PORT_1D" Name="PORT_WLAN_SPI_CS_N"/>
+
+            <!-- Button ports -->
+            <Port Location="XS1_PORT_4C" Name="PORT_BUT_A_TO_D"/>
+
+            <!-- LED ports -->
+            <Port Location="XS1_PORT_8C" Name="PORT_LED0_TO_7"/>
+            <!-- Note: Only bits 4-7 of PORT 8D are for LEDs -->
+            <Port Location="XS1_PORT_8D" Name="PORT_LED8_TO_11"/>
+            <Port Location="XS1_PORT_1J" Name="PORT_LED_12"/>
+          </Tile>
+        </Node>
+      </Nodes>
+    </Package>
+  </Packages>
+
+  <Links>
+    <Link Encoding="2wire" Delays="3clk">
+      <LinkEndpoint NodeId="0" Link="7"/>
+      <LinkEndpoint NodeId="2" Link="0"/>
+    </Link>
+    <Link Encoding="5wire" Delays="3clk">
+      <LinkEndpoint NodeId="0" Link="4"/>
+      <LinkEndpoint NodeId="2" Link="3"/>
+    </Link>
+  </Links>
+
+  <!-- XSCOPE -->
+  <Nodes>
+    <Node Id="3" Type="device:" RoutingId="0x8000">
+      <Service Id="0" Proto="xscope_host_data(chanend c);">
+        <Chanend Identifier="c" end="3"/>
+      </Service>
+    </Node>
+  </Nodes>
+  <Links>
+    <Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
+      <LinkEndpoint NodeId="0" Link="XL0"/>
+      <LinkEndpoint NodeId="3" Chanend="1"/>
+    </Link>
+  </Links>
+
+  <ExternalDevices>
+    <Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash0">
+      <Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
+      <Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
+      <Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
+    </Device>
+  </ExternalDevices>
+
+  <JTAGChain>
+    <JTAGDevice NodeId="0"/>
+    <JTAGDevice NodeId="2"/>
+  </JTAGChain>
+
+</Network>

From 3a6a84d78748859ec2cd660f016fce92152a949e Mon Sep 17 00:00:00 2001
From: robert lytton <robert@xmos.com>
Date: Wed, 22 Nov 2017 13:46:02 +0000
Subject: [PATCH 06/10] Added random_bit, random_pool, random_prng interfaces

deprecated random_create_generator_from_hw_seed() making it's build conditional (add 'RANDOM_ENABLE_HW_SEED=1' to the Makefile)
---
 .../src/random_numbers.xc                     | 204 ++++++++----------
 lib_random/api/random.h                       |  49 +----
 lib_random/api/random_bit.h                   |  60 ++++++
 lib_random/api/random_pool.h                  |  74 +++++++
 lib_random/api/random_prng.h                  |  70 ++++++
 lib_random/doc/rst/random.rst                 |   4 +-
 lib_random/module_build_info                  |  20 +-
 lib_random/src/random.xc                      |  15 +-
 lib_random/src/random_bit.xc                  |  71 ++++++
 lib_random/src/random_deprecated.c            |  21 ++
 lib_random/src/random_impl.h                  |  20 ++
 lib_random/src/random_init.c                  |  17 --
 lib_random/src/random_pool.xc                 | 172 +++++++++++++++
 lib_random/src/random_prng.xc                 | 166 ++++++++++++++
 lib_random/src/true_random.xc                 |  48 -----
 test/random/Makefile                          |  14 ++
 test/random/expected.output                   |   4 +
 test/random/src/test.xc                       | 130 +++++++++++
 test/random_bit/Makefile                      |  18 ++
 test/random_bit/expected.output               |   6 +
 test/random_bit/src/test.xc                   | 199 +++++++++++++++++
 test/random_pool/Makefile                     |  11 +
 test/random_pool/expected.output              |   6 +
 test/random_pool/src/test.xc                  | 201 +++++++++++++++++
 test/random_prng/Makefile                     |  13 ++
 test/random_prng/expected.output              |  16 ++
 test/random_prng/src/test.xc                  |  77 +++++++
 test/runtests.py                              |   9 +
 test/test_random.py                           |  15 ++
 test/test_random_bit.py                       |  15 ++
 test/test_random_pool.py                      |  15 ++
 test/test_random_prng.py                      |  15 ++
 32 files changed, 1535 insertions(+), 240 deletions(-)
 mode change 100644 => 100755 lib_random/api/random.h
 create mode 100755 lib_random/api/random_bit.h
 create mode 100755 lib_random/api/random_pool.h
 create mode 100755 lib_random/api/random_prng.h
 mode change 100644 => 100755 lib_random/module_build_info
 mode change 100644 => 100755 lib_random/src/random.xc
 create mode 100755 lib_random/src/random_bit.xc
 create mode 100755 lib_random/src/random_deprecated.c
 create mode 100755 lib_random/src/random_impl.h
 delete mode 100644 lib_random/src/random_init.c
 create mode 100755 lib_random/src/random_pool.xc
 create mode 100755 lib_random/src/random_prng.xc
 delete mode 100644 lib_random/src/true_random.xc
 create mode 100644 test/random/Makefile
 create mode 100644 test/random/expected.output
 create mode 100755 test/random/src/test.xc
 create mode 100755 test/random_bit/Makefile
 create mode 100644 test/random_bit/expected.output
 create mode 100755 test/random_bit/src/test.xc
 create mode 100644 test/random_pool/Makefile
 create mode 100644 test/random_pool/expected.output
 create mode 100755 test/random_pool/src/test.xc
 create mode 100644 test/random_prng/Makefile
 create mode 100644 test/random_prng/expected.output
 create mode 100755 test/random_prng/src/test.xc
 create mode 100755 test/runtests.py
 create mode 100755 test/test_random.py
 create mode 100755 test/test_random_bit.py
 create mode 100755 test/test_random_pool.py
 create mode 100755 test/test_random_prng.py

diff --git a/examples/AN002xx_random_number_generation/src/random_numbers.xc b/examples/AN002xx_random_number_generation/src/random_numbers.xc
index e369c94..3c94404 100644
--- a/examples/AN002xx_random_number_generation/src/random_numbers.xc
+++ b/examples/AN002xx_random_number_generation/src/random_numbers.xc
@@ -4,7 +4,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <xs1.h>
-#include "random.h"
+#include "random_bit.h"
 
 #define MAXX 1024
 #define MAXY 1024
@@ -13,140 +13,124 @@
 unsigned char thebits[MAXBITS/8];
 
 unsigned int getbit(int i) {
-    return (thebits[i>>3] >> (i&7)) & 1;
+  return (thebits[i>>3] >> (i&7)) & 1;
 }
 
 unsigned int setbit(int i, int val) {
-    return thebits[i>>3] |= val << (i&7);
+  return thebits[i>>3] |= val << (i&7);
 }
 
 void blocktest(int n) {
-    int hist[256];
-    for(int i = 0; i < 256; i++) {
-        hist[i] = 0;
+  int hist[256];
+  for(int i = 0; i < 256; i++) {
+    hist[i] = 0;
+  }
+  for(int i = 0; i < MAXBITS - n; i++) {
+    int val = 0;
+    for(int j = 0; j < n; j++) {
+      val = val << 1 | getbit(i+j);
     }
-    for(int i = 0; i < MAXBITS - n; i++) {
-        int val = 0;
-        for(int j = 0; j < n; j++) {
-            val = val << 1 | getbit(i+j);
-        }
-        hist[val]++;
-    }
-    printf("Blocktest %d\n", n);
-    for(int i = 0; i < (1<<n); i++) {
-        printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i]-(MAXBITS >> n)) < MAXX ? "Ok" : "Hmm");
-    }
-    printf("\n");
+    hist[val]++;
+  }
+  printf("Blocktest %d\n", n);
+  for(int i = 0; i < (1<<n); i++) {
+    printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i]-(MAXBITS >> n)) < MAXX ? "Ok" : "Hmm");
+  }
+  printf("\n");
 }
 
 void runtest() {
-    int hist[200];
-    int old = 0;
-    int run = 0;
-    for(int i = 0; i < 200; i++) {
-        hist[i] = 0;
-    }
-    for(int i = 0; i < MAXBITS; i++) {
-        if(getbit(i) == old) {
-            run++;
-        } else {
-            hist[run]++;
-            run = 1;
-        }
-    }
-    printf("Runtest:\n");
-    for(int i = 1; i < 10; i++) {
-        printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i] - (MAXBITS >> (i+1))) < (MAXX >> (i/2)) ? "Ok" : "Hmm" );
-    }
-    printf("\n");
-}
-
-void fillmepseudo(void) {
-    random_generator_t rt = random_create_generator_from_seed(0);
-    int sum = 0;
-    random_true_init();
-    while(sum < MAXBITS) {
-        unsigned rand = random_get_random_number(rt);
-        for(int i = 0; i < 32 && sum < MAXBITS; i++) {
-            setbit(sum, rand & 1);
-            rand >>= 1;
-            sum++;
-        }
+  int hist[200];
+  int old = 0;
+  int run = 0;
+  for(int i = 0; i < 200; i++) {
+    hist[i] = 0;
+  }
+  for(int i = 0; i < MAXBITS; i++) {
+    if(getbit(i) == old) {
+      run++;
+    } else {
+      hist[run]++;
+      run = 1;
     }
+  }
+  printf("Runtest:\n");
+  for(int i = 1; i < 10; i++) {
+    printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i] - (MAXBITS >> (i+1))) < (MAXX >> (i/2)) ? "Ok" : "Hmm" );
+  }
+  printf("\n");
 }
 
 void fillmetrue(void) {
-    int n, rand;
-    timer tmr;
-    int t0, t1;
-    int sum = 0;
-    random_true_init();
-    tmr :> t0;
-    while(sum < MAXBITS) {
-        {n, rand} = random_true_get_bits();
-        if (n == 0) {
-           // tmr when timerafter(rand) :> void;
-        } else {
-            for(int i = 0; i < n && sum < MAXBITS; i++) {
-                setbit(sum, rand & 1);
-                rand >>= 1;
-                sum++;
-            }
-            if ((sum & 0xffff) == 0) {
-                int time;
-                asm volatile ("gettime %0" : "=r" (time));
-                printf("%11d %d\n", time, sum);
-            }
-        }
+  timer tmr;
+  int t0, t1;
+  int sum = 0;
+  tmr :> t0;
+  random_bit_start();
+  while(sum < MAXBITS) {
+    uint32_t bit_time;
+    if (random_bit(bit_time)) {
+      //assert((bit_time & ~1UL)==0);
+      setbit(sum, bit_time);
+      sum++;
+      if ((sum & 0xffff) == 0) {
+        int time;
+        asm volatile ("gettime %0" : "=r" (time));
+        printf("%11d %d\n", time, sum);
+      }
     }
-    tmr :> t1;
-    printf("Ticks taken: %d, %d per bit\n", t1-t0, (t1-t0)/sum);
+    //else
+    //  tmr when timerafter(bit_time) :> void;
+  }
+  random_bit_stop();
+  tmr :> t1;
+  printf("Ticks taken: %d, %d per bit\n", t1-t0, (t1-t0)/sum);
 }
 
 void xmain(chanend done[7]) {
-    for(int i = 0; i < 7; i++) {
-        done[i] <: 0;
-    }
-    fillmetrue();
-    blocktest(1);
-    blocktest(2);
-    blocktest(3);
-    runtest();
-    return;
-    printf("P2\n%d %d\n1\n", MAXX, MAXY);
-    for(int i = 0; i < MAXX; i++) {
-        for(int j = 0; j < MAXY; j++) {
-            printf("%d ", getbit(i*MAXY+j));
-        }
-        printf("\n");
+  for(int i = 0; i < 7; i++) {
+    done[i] <: 0;
+  }
+  fillmetrue();
+  blocktest(1);
+  blocktest(2);
+  blocktest(3);
+  runtest();
+  return;
+  printf("P2\n%d %d\n1\n", MAXX, MAXY);
+  for(int i = 0; i < MAXX; i++) {
+    for(int j = 0; j < MAXY; j++) {
+      printf("%d ", getbit(i*MAXY+j));
     }
+    printf("\n");
+  }
 }
 
 int busy(int x, chanend y) {
-    while(1) {
-        for(int i = 0; i < 1000; i++) {
-            x = x * 1234567 + 1;
-        }
-        select {
-            case y :> int _: return x;
-            default:  break;
-        }
+  while(1) {
+    for(int i = 0; i < 1000; i++) {
+      x = x * 1234567 + 1;
+    }
+    select {
+      case y :> int _: return x;
+      default:  break;
     }
-    return x;
+  }
+  return x;
 }
 
 
 int main(void) {
-    chan done[7];
-    par {
-        busy(0x3, done[0]);
-        busy(0x4, done[1]);
-        busy(0x5, done[2]);
-        busy(0x6, done[3]);
-        busy(0x7, done[4]);
-        busy(0x8, done[5]);
-        busy(0x9, done[6]);
-        xmain(done);
-    }
-    return 0;
+  chan done[7];
+  par {
+    busy(0x3, done[0]);
+    busy(0x4, done[1]);
+    busy(0x5, done[2]);
+    busy(0x6, done[3]);
+    busy(0x7, done[4]);
+    busy(0x8, done[5]);
+    busy(0x9, done[6]);
+    xmain(done);
+  }
+  return 0;
 }
diff --git a/lib_random/api/random.h b/lib_random/api/random.h
old mode 100644
new mode 100755
index 5a506fc..fec5350
--- a/lib_random/api/random.h
+++ b/lib_random/api/random.h
@@ -13,6 +13,11 @@
 #endif
 #endif
 
+/** This is an alternative pseudo-random number generator to those offered by stdlib.h:
+ *  rand, srand, rand_r, drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, seed48, srand48
+ *  It uses the built in crc32() instructions.
+ */
+
 /** Type representing a random number generator.
  */
 typedef unsigned random_generator_t;
@@ -26,15 +31,6 @@ typedef unsigned random_generator_t;
 random_generator_t random_create_generator_from_seed(unsigned seed);
 
 
-/** Function that attempts to create a random number generator from
- *  a true random value into the seed, using
- *  an asynchronous timer. To use this function you must enable the
- *  ``RANDOM_ENABLE_HW_SEED`` define in your application's ``random_conf.h``.
- *
- *  \returns a random number generator.
- */
-random_generator_t random_create_generator_from_hw_seed(void);
-
 /** Function that produces a random number. The number has a cycle of 2^32
  *  and is produced using a LFSR.
  *
@@ -47,36 +43,13 @@ random_get_random_number(REFERENCE_PARAM(random_generator_t, g));
 
 void random_get_random_bytes(REFERENCE_PARAM(random_generator_t, g), uint8_t in_buffer[], size_t byte_count);
 
-#ifdef __XC__
-/** Function that produces a number of random bits. It returns two
- * integers.
- *
- * If random bits are available, then it returns the number of random bits,
- * and the actual random bits.
- *
- * If no random bits are available, then it returns 0 (for no random bits)
- * and the time in ticks at which new bits are available. The code can wait
- * for this time (for example in a select statement), and then collect the
- * random bits.
- * 
- * At most 16 random bits are returned. To get a large number of random
- * bits this function should be called regularly. Calling it too quickly
- * since a previous call will return 0.
- *
- * \returns Number of bits, and random bits, or 0 and timestamp in the future.
- */
-{uint32_t,int32_t} random_true_get_bits();
 
-/** Function that initialises the true random number generator. Calling
- * this function will start the free running oscillator. This will take a
- * bit of extra power.
- */
-void random_true_init();
+// The following function is deprecated.
+// It is incompatible with the rest of the lib_random library.
+// To use this function you must define in your Makefile:
+//    RANDOM_ENABLE_HW_SEED=1
+//__attribute__((deprecated)) // Use random_prng.h instead.
+random_generator_t random_create_generator_from_hw_seed(void);
 
-/** Function that uninitialises the true random number generator. This will
- * stop the ring oscillator, and reduce the power foot print a little.
- */
-void random_true_uninit();
-#endif
 
 #endif // __RANDOM_H__
diff --git a/lib_random/api/random_bit.h b/lib_random/api/random_bit.h
new file mode 100755
index 0000000..0aaf87b
--- /dev/null
+++ b/lib_random/api/random_bit.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+#ifndef __RANDOM_BIT_H__
+#define __RANDOM_BIT_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+#ifndef REFERENCE_PARAM
+#ifdef __XC__
+#define REFERENCE_PARAM(type, name) type &name
+#else
+#define REFERENCE_PARAM(type, name) type *name
+#endif
+#endif
+
+
+/** The random_bit.h library is NOT thread safe.
+ *
+ * There is one oscillator per tile, hence there may be one user of the library per tile.
+ * However, on a multi-tile device, each tile may have one thread calling the library.
+ */
+
+
+/** Functions used to claim and release the random_bit library.
+ *
+ * As is only one oscillator per tile, there may only be one user of the
+ * library per tile.
+ *
+ * random_bit_claim() returns 0 if the library has already been claimed on
+ * this tile.
+ *
+ * N.B. Ownership of the library does not prevent others from calling it!
+ */
+int random_bit_claim();
+void random_bit_release();
+
+/** Functions that start & stop the random number generator.
+ *
+ * Calling this function will start/stop the free running oscillator.
+ * A running oscillator will increase power consumption by a few mW.
+ *
+ * N.B. There is no checking that the caller has previously claimed the library.
+ */
+void random_bit_start();
+void random_bit_stop();
+
+/** Function that produces a random bit.
+ *
+ * If random bits are available, then it returns '1' and the random bit.
+ *
+ * If no random bits are available, then it returns 0 and the absolute
+ * time in ticks at which a bit will be available.
+ * The calling code may then wait until this time (for example in a select statement),
+ * recalling the function when the bit will be available.
+ *
+ * N.B. There is no checking that the caller has previously claimed the library.
+ */
+uint32_t random_bit(REFERENCE_PARAM(uint32_t, bit_time));
+
+#endif // __RANDOM_BIT_H__
diff --git a/lib_random/api/random_pool.h b/lib_random/api/random_pool.h
new file mode 100755
index 0000000..6ed6f2f
--- /dev/null
+++ b/lib_random/api/random_pool.h
@@ -0,0 +1,74 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+#ifndef __RANDOM_POOL_H__
+#define __RANDOM_POOL_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include "random_impl.h"
+
+/** Interface for clients to request bits from a random pool.
+ *
+ * Multiple clients, situated on any tile, may receive bits from a server.
+ * There may be only one server per tile.
+ *
+ * The server task calls random_bit_claim() for the tile.
+ * If the claim fails, the task will exit immediately.
+ */
+interface random_pool {
+/** Method that returns the maximum bits a pool can hold. */
+  size_t capacity();
+
+/** Method that returns the number of bits available in the pool. */
+  size_t available();
+
+/** Method that returns the approximate period until `bits` will be available.
+ *
+ * Clients may then callback or sleep whilst waiting for the pool to fill.
+ * The client will need to do multiple `fetch()` followed by waits if
+ * there are multiple clients calling `fetch() or if `bits` > `capacity()`.
+ */
+  uint32_t timeUntil(size_t bits);
+
+/** Method that overwrites `value[ bitPos : bitPos+numBits ]` with random bits.
+ *
+ * The bit range will be truncated to fit within value[].
+ *
+ * \returns   The number of bits overwritten, starting at 'bitPos'.
+ *            This will be the same as numBits if the bits are available.
+ */
+  size_t insert(uint32_t& value, size_t bitPos, size_t numBits);
+
+/** Method exits the random_pool server task when all clients have released.
+ *
+ *  This allows a combined-par to exit if/when the client owning tasks exits.
+ *  random_bit_release() will be called, allowing another task to claim it.
+ */
+  void release();
+};
+
+/** Type represents an opaque bit pool size. */
+typedef size_t PoolSize_t;
+
+/** Helper function for turning the minimum number of bits into a `PoolSize_t` opaque value.
+ *
+ *  N.B. As `PoolSize_t` values are opaque, they must be generated via this function!
+ *  PoolSize_t bitsToPoolSize(size_t bits);
+ */
+#define bitsToPoolSize(bits) _bitsToPoolSize(bits)
+
+/** Server task that collects random bits into a pool.
+ *
+ * The server task may be combined with other tasks in a combined-par statement.
+ * There may be one server task per tile (as there is only one random_bit generator per tile).
+ * Clients may then request random bits from the sever task's pool via the `interface random_pool`.
+ * There may be multiple clients, situated on a mixture of tile.
+ *
+ * \param rpi        Server end of an `interface random_pool`.
+ * \param n          Number of `client interface random_pool`s being served.
+ * \param poolSize   Size of random bit pool to create - N.B. use bitsToPoolSize() to generate the value.
+ */
+[[combinable]]
+void random_pool_server(server interface random_pool rpi[n], static const size_t n,
+                        static const PoolSize_t poolSize);
+
+#endif // __RANDOM_POOL_H__
diff --git a/lib_random/api/random_prng.h b/lib_random/api/random_prng.h
new file mode 100755
index 0000000..83a22ec
--- /dev/null
+++ b/lib_random/api/random_prng.h
@@ -0,0 +1,70 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+#ifndef __RANDOM_PRNG_H__
+#define __RANDOM_PRNG_H__
+
+#include <stdint.h>
+#include <stddef.h>
+#include "random_impl.h"
+#include "random_pool.h"
+
+
+/** Interface for a client to request pseudo-random numbers. */
+interface random_prng {
+
+/** Method that returns a pseudo-random number.
+ *
+ *  ====== WARNING ====================================================
+ *  The PRNG is a simple CRC and hence is not cryptographically secure.
+ *  Exposing a value outside of the chip exposes the entire sequence.
+ *  See random_csprng for how to hash the PRNG to make it secure.
+ *
+ *  If n > 1, the PRNG will be called mulitple times to retrived 32bit values.
+ */
+  void value(uint32_t values[n], size_t n);
+
+/** The following methods perturbe the PRNG with bits from a random_pool of true random bits.
+ *  Each returns the numbe of bits actually taken from the random_pool.
+ */
+  size_t perturbe_nonBlocking(size_t numBits); // Returns the numBits actually used (available).
+  size_t perturbe_blocking(size_t numBits);    // Blocks until 'numBits' are available to use.
+  size_t perturbe_halfAvailableBits();         // Uses half the available bits in the pool.
+
+/** Method exits the random_prng server task.
+ *
+ *  This allows a combined-par to exit if/when the client owning task exits.
+ *  N.B. The user owns the random_pool client (passed to the server) and
+ *       they must call `rpi.release()` when they have finished with it.
+ */
+  void release();
+};
+
+/** A type that specifies the repeat range for the PRNG
+ *
+ * There are 3 choices offering 32bit sequences of ~2^57, ~2^88 and ~2^113 in length.
+ * The processing time will increase with the PrngSize.
+ * The enumerated value is the number of uint32_t required to 'seed' the generator.
+ */
+typedef enum {prng57=2, prng88=3, prng113=4} PrngSize;
+
+/** Server task that generates the pseudo-random number.
+ *
+ * This is a 1:1 relationship.
+ * The call to perturbe_blocking() will 'sleep' both the client and server.
+ * Being distributable, the server-code will be inlined into the client task.
+ *
+ * N.B. Using the same client (PRNG stream) for muliple consumers will result in
+ *      the consumers recieving correlated numbers (shared state).
+ *      If correlation is an issue, consumers must instantiate their own
+ *      server-client pair with a unique seed.
+ *
+ * \param prngi     Server end of an `interface random_PRNG`.
+ * \param rpi       Client end of an `interface random_pool`.
+ * \param prngSize  Either 'prng57', 'prng88' or 'prng113'.
+ * \param seed      Optional seed for the PRNG (or null)
+ *                  N.B. each seed[] entry must be > 127, the default value is 128.
+ */
+[[distributable]]
+void random_prng_server(server interface random_prng prngi, client interface random_pool rpi,
+                        static const PrngSize prngSize, uint32_t (&?seed)[prngSize]);
+
+#endif // __RANDOM_PRNG_H__
diff --git a/lib_random/doc/rst/random.rst b/lib_random/doc/rst/random.rst
index 57919d2..389f89a 100644
--- a/lib_random/doc/rst/random.rst
+++ b/lib_random/doc/rst/random.rst
@@ -15,7 +15,7 @@ include the ``random.h`` header.
 Known Issues
 ------------
 
-There are no known issues with this library.
-
+The deprecated random_create_generator_from_hw_seed() functionality will not work corrrectly
+along side random_bit.h (and hence random_pool.h and random_prng.h)
 
 .. include:: ../../../CHANGELOG.rst
diff --git a/lib_random/module_build_info b/lib_random/module_build_info
old mode 100644
new mode 100755
index 2c8f3cc..0828bac
--- a/lib_random/module_build_info
+++ b/lib_random/module_build_info
@@ -1,14 +1,10 @@
-# You can set flags specifically for your module by using the MODULE_XCC_FLAGS
-# variable. So the following
-#
-#   MODULE_XCC_FLAGS = $(XCC_FLAGS) -O3
-#
-# specifies that everything in the modules should have the application
-# build flags with -O3 appended (so the files will build at
-# optimization level -O3).
-#
-# You can also set MODULE_XCC_C_FLAGS, MODULE_XCC_XC_FLAGS etc..
-
 MODULE_XCC_FLAGS = -g -Os
+#MODULE_XCC_FLAGS += -save-temps -v
+
+# Enable deprecated features
+ifneq ($(RANDOM_ENABLE_HW_SEED),)
+MODULE_XCC_FLAGS += -DRANDOM_ENABLE_HW_SEED=$(RANDOM_ENABLE_HW_SEED)
+endif
 
-VERSION = 1.0.0
+DEPENDENT_MODULES = lib_locks lib_xassert
+VERSION = 1.1.0
diff --git a/lib_random/src/random.xc b/lib_random/src/random.xc
old mode 100644
new mode 100755
index 2bbc8ff..9d32dfe
--- a/lib_random/src/random.xc
+++ b/lib_random/src/random.xc
@@ -2,18 +2,16 @@
 #include "random.h"
 #include <xs1.h>
 
-static const unsigned random_poly = 0xEDB88320;
-
 unsigned random_get_random_number(random_generator_t &g)
 {
+  static const unsigned random_poly = 0xEDB88320;
   crc32(g, -1, random_poly);
   return (unsigned) g;
 }
 
 void random_get_random_bytes(random_generator_t &g, uint8_t in_buffer[], size_t byte_count)
 {
-  for (int i=0; i < byte_count; i++)
-  {
+  for (int i=0; i < byte_count; ++i) {
     in_buffer[i] = (uint8_t)random_get_random_number(g);
   }
 }
@@ -24,12 +22,3 @@ random_generator_t random_create_generator_from_seed(unsigned seed)
   (void) random_get_random_number(gen);
   return gen;
 }
-
-static const unsigned XS1_L_RING_OSCILLATOR_VALUE_REG  = 0x070B;
-
-random_generator_t random_create_generator_from_hw_seed(void)
-{
-  unsigned init_seed = getps(XS1_L_RING_OSCILLATOR_VALUE_REG);
-  return random_create_generator_from_seed(init_seed);
-}
-
diff --git a/lib_random/src/random_bit.xc b/lib_random/src/random_bit.xc
new file mode 100755
index 0000000..3b48acc
--- /dev/null
+++ b/lib_random/src/random_bit.xc
@@ -0,0 +1,71 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+#include "random_bit.h"
+#include "hwlock.h"
+#include "random_impl.h"
+
+// Optional thread protection...
+
+#define LOAD32(dst, ptr)       asm("ldw %0, %1[0]"  : "=r"(dst) : "r"(ptr));
+#define STORE32(src, ptr)      asm("stw %0, %1[0]"  :           : "r"(src), "r"(ptr));
+
+extern unsigned __libc_hwlock;
+static int per_tile_available = 1;
+
+int random_bit_claim() {
+  int available;
+  hwlock_acquire(__libc_hwlock);
+  LOAD32(available, &per_tile_available);
+  if (available) {
+    int newValue = 0;
+    STORE32(newValue, &per_tile_available);
+  }
+  hwlock_release(__libc_hwlock);
+  return available;
+}
+
+void random_bit_release() {
+  int newValue = 1;
+  STORE32(newValue, &per_tile_available);
+}
+
+
+// None thread safe code...
+
+static int per_tile_last_time = 0;
+
+void random_bit_start() {
+  int last_time;
+  timer tmr;
+  tmr :> last_time;
+  STORE32(last_time, &per_tile_last_time);
+  setps(0x60B, 2);
+}
+
+void random_bit_stop() {
+  setps(0x60B, 0);
+}
+
+uint32_t random_bit(uint32_t &bit_time) {
+  int last_time;
+  LOAD32(last_time, &per_tile_last_time);
+  timer tmr;
+  uint32_t time;
+  tmr :> time;
+  // If the timer wraps, we will miss the opportunity - tough!
+  // N.B. unsigned wrapping has defined behaviour.
+  if (time - last_time > TIME_FOR_ONE_BIT) {
+    random_bit_stop();
+    asm("nop");
+    asm("nop");
+    asm("nop");
+    asm("nop");
+    bit_time = getps(0x70B);
+    random_bit_start();
+    bit_time &=1;
+    return 1;
+  }
+  else {
+    bit_time = last_time + TIME_FOR_ONE_BIT;
+    return 0;
+  }
+}
diff --git a/lib_random/src/random_deprecated.c b/lib_random/src/random_deprecated.c
new file mode 100755
index 0000000..711102e
--- /dev/null
+++ b/lib_random/src/random_deprecated.c
@@ -0,0 +1,21 @@
+// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
+#include "random.h"
+#include <xs1.h>
+
+#if RANDOM_ENABLE_HW_SEED
+
+#warning "Building deprecated random_create_generator_from_hw_seed()"
+#warning "N.B. random_create_generator_from_hw_seed() is incompatible with the rest of the lib_random library."
+#warning "Did you mean to define `RANDOM_ENABLE_HW_SEED`?"
+
+__attribute__((constructor))
+void random_simple_init_seed() {
+  setps(0x060B, 0x3);
+}
+
+random_generator_t random_create_generator_from_hw_seed(void) {
+  unsigned init_seed = getps(0x070B);
+  return random_create_generator_from_seed(init_seed);
+}
+
+#endif
diff --git a/lib_random/src/random_impl.h b/lib_random/src/random_impl.h
new file mode 100755
index 0000000..1311e7a
--- /dev/null
+++ b/lib_random/src/random_impl.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+#ifndef __RANDOM_IMPL_H__
+#define __RANDOM_IMPL_H__
+
+#include <stdint.h>
+
+// Used by random_bit() & random_pool_server()
+#define TIME_FOR_ONE_BIT 20000
+
+// N.B. _rp_impl_type is NOT part of the interface.
+//      as part of the implementation it may change at any time.
+typedef uint8_t _rp_impl_type;
+// random_pool_server() : assert(sizeof(uint32_t) >= sizeof(_rp_impl_type) && "memcpy needs fixing");
+
+
+// N.B. The implementation requires an extra bit for indexing efficiency,
+//      hence we do NOT use `(b+(N-1))/N` rounding.
+#define _bitsToPoolSize(bits) (((bits) / (sizeof(_rp_impl_type)*8)) + 1)
+
+#endif // __RANDOM_IMPL_H__
diff --git a/lib_random/src/random_init.c b/lib_random/src/random_init.c
deleted file mode 100644
index a9a9a4b..0000000
--- a/lib_random/src/random_init.c
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
-#include "random.h"
-#include <xs1.h>
-
-static const unsigned XS1_L_RING_OSCILLATOR_CONTROL_REG    = 0x060B;
-static const unsigned XS1_L_RING_OSCILLATOR_CONTROL_START  = 0x3;
-
-__attribute__((constructor))
-void random_simple_init_seed()
-{
-/* This constructor starts of the ring oscillator when the program loads.
-   This will run on an asynchronous time base to the main xCORE. By starting it
-   off now the later call to random_create_generator_from_hw_seed will pick up
-   a value later which has drifted to a random state */
-  setps(XS1_L_RING_OSCILLATOR_CONTROL_REG,
-        XS1_L_RING_OSCILLATOR_CONTROL_START);
-}
diff --git a/lib_random/src/random_pool.xc b/lib_random/src/random_pool.xc
new file mode 100755
index 0000000..14ca39b
--- /dev/null
+++ b/lib_random/src/random_pool.xc
@@ -0,0 +1,172 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+
+#include "random_pool.h"
+#include <xs1.h>
+#include <string.h>
+#include "xassert.h"
+#include "random_bit.h"
+
+// We always want xassert(e) to trap.
+#if !(XASSERT_ENABLE_ASSERTIONS0)
+# undef xassert
+# define xassert(e) do { if (!(e)) __builtin_trap();} while(0)
+#endif
+
+// Internally, we use bit indexes into the pool (head, tail etc).
+// To make head/tail handling easier and more efficient:
+//   head==tail means empty;
+//   we will always have at least one bit 'empty'.
+// See _bitsToPoolSize() macro for extra bit calculation.
+
+static inline size_t poolSizeInBits(static const PoolSize_t poolSize) {
+  return poolSize * (sizeof(_rp_impl_type)*8);
+}
+
+static inline size_t poolSizeCapacity(static const PoolSize_t poolSize) {
+  return poolSizeInBits(poolSize) - 1; // see comment above.
+}
+
+static inline size_t available(size_t head, size_t tail, static const PoolSize_t poolSize) {
+  if (tail > head)
+    head += poolSizeInBits(poolSize);
+  return head - tail;
+}
+
+// incrementor for bit position
+static inline void incrementPos(size_t& pos, static const PoolSize_t poolSize) {
+  ++pos;
+  if (pos == poolSizeInBits(poolSize))
+    pos = 0;
+}
+
+// Convert the `head` and `tail` bit positions into `_rp_impl_type[]` accessors.
+static inline size_t indexOffset(size_t pos) {
+  return pos / (sizeof(_rp_impl_type)*8);
+}
+static inline size_t bitOffset(size_t pos) {
+  return pos % (sizeof(_rp_impl_type)*8);
+}
+
+static inline _rp_impl_type bitMask(size_t numBits) {
+  return (1ULL << numBits) - 1;
+}
+
+static inline uint32_t poolFill(size_t& head, size_t& tail,
+                                _rp_impl_type pool[poolSize], static const PoolSize_t poolSize) {
+  uint32_t bit_time;
+  while (random_bit(bit_time)) {
+    // xor the bit at 'head'.
+    pool[indexOffset(head)] ^= (bit_time << bitOffset(head));
+    incrementPos(head, poolSize);
+    if (head == tail) { // We have a full pool.
+      // Throw away old bits and keep the newest (always one bit empty).
+      incrementPos(tail, poolSize);
+    }
+  }
+  return bit_time; // Time when next bit available.
+}
+
+static inline void xorInsert(uint32_t& value, size_t bitPos, size_t numBits,
+                          size_t& tail, _rp_impl_type pool[poolSize], static const PoolSize_t poolSize ) {
+  // asserted (bitPos+numBits <= 32), bits will map onto a single uint32_t 'value'.
+
+  // Initialise the pool access variables, we will update them in the loop.
+  size_t tailIndex = indexOffset(tail);
+  size_t tailBit = bitOffset(tail); // zero on subsequent passes.
+
+  // Update 'tail' assuming we will remove 'numBits'.
+  // asserted (numBits<=available() && numBits < poolSizeInBits), so we wont need to worry about head.
+  tail += numBits;
+  if (tail >= poolSizeInBits(poolSize))
+    tail -= poolSizeInBits(poolSize);
+
+  while (numBits) {
+    size_t allotted = (sizeof(_rp_impl_type)*8) - tailBit; // Initially grab all top bits...
+    size_t invalidTop = 0;                                 // so we don't discard any top bits.
+    if (allotted > numBits) {
+      // We don't need them all (or they are not available).
+      allotted = numBits;
+      invalidTop = (sizeof(_rp_impl_type)*8) - (tailBit + allotted);
+    }
+    _rp_impl_type v = pool[tailIndex];
+    v <<= invalidTop;               // Mask top bits.
+    v >>= (tailBit + invalidTop);   // Mask bottom bits.
+    v <<= bitPos;                   // Position bits ready for insertion.
+    value ^= v;                     // xor-ing does not affect the randomness quality.
+
+    numBits -= allotted;
+    if (numBits) {
+      // Update loop variables.
+      bitPos += allotted;
+      ++tailIndex;
+      if (tailIndex == poolSize)
+        tailIndex = 0;
+      tailBit = 0;
+    }
+  }
+}
+
+[[combinable]]
+void random_pool_server(server interface random_pool rpi[numClients], static const size_t numClients,
+                        static const PoolSize_t poolSize) {
+  if (!random_bit_claim()) {
+    xassert(0); // "You can have only one random_pool_server task per tile."
+  }
+
+  // We will release when the last client has released us.
+  // All clients have implicitly claimed us, set the 'numClients' lowest bits.
+  xassert(numClients <= 32); // "The maximum number of clients is 32".
+  uint32_t activeClients = (1ULL<<numClients) - 1;
+
+  _rp_impl_type pool[poolSize];
+  size_t head = 0; // The fill point.
+  size_t tail = 0; // The removal point.
+
+  uint32_t time = poolFill(head, tail, pool, poolSize);
+  timer tmr;
+
+  while(1) {
+    select {
+      case rpi[unsigned id].capacity() -> size_t numBits:
+        numBits = poolSizeCapacity(poolSize);
+        break;
+
+      case rpi[unsigned id].available() -> size_t numBits:
+        numBits = available(head, tail, poolSize);
+       break;
+
+      case rpi[unsigned id].timeUntil(size_t numBits) -> uint32_t period:
+        if (numBits > poolSizeCapacity(poolSize))
+          numBits = poolSizeCapacity(poolSize);
+        size_t bits = available(head, tail, poolSize);
+        period = (numBits < bits)? 0 : (numBits - bits) * TIME_FOR_ONE_BIT;
+        break;
+
+      case rpi[unsigned id].insert(uint32_t& value, size_t bitPos, size_t numBits) -> size_t bits:
+        if (bitPos > 31)
+          numBits = 0;
+        if (numBits > sizeof(uint32_t)*8 - bitPos)
+          numBits = sizeof(uint32_t)*8 - bitPos;
+        size_t avail = available(head, tail, poolSize);
+        bits = (numBits > avail)? avail : numBits;
+        if (bits) {
+          uint32_t local = value;  // Can't use remote-references as argument :-(
+          xorInsert(local, bitPos, bits, tail, pool, poolSize);
+          value = local;
+        }
+        break;
+
+      case rpi[unsigned id].release():
+        activeClients &= ~(1UL << id);
+        if (!activeClients) {
+          random_bit_release();
+          return;
+        }
+        break;
+
+      case  tmr when timerafter(time) :> void:
+        time = poolFill(head, tail, pool, poolSize);
+        break;
+    }
+  }
+}
diff --git a/lib_random/src/random_prng.xc b/lib_random/src/random_prng.xc
new file mode 100755
index 0000000..bf3d445
--- /dev/null
+++ b/lib_random/src/random_prng.xc
@@ -0,0 +1,166 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+
+#include "random_prng.h"
+#include <xs1.h>
+#include <string.h>
+#include "xassert.h"
+#include "random_pool.h"
+
+// We always want xassert(e) to trap.
+#if !(XASSERT_ENABLE_ASSERTIONS0)
+# undef xassert
+# define xassert(e) do { if (!(e)) __builtin_trap();} while(0)
+#endif
+
+// From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe Generators"
+// Mathematics of Computation, 65, 213 (1996), 203--213:
+// www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
+static uint32_t quickTaus(uint32_t state, uint32_t c,
+                          uint32_t q, uint32_t s, uint32_t k_s) {
+  return (((state << q) ^ state) >> k_s) ^ ((state & c) << s);
+}
+#define QT_PARAMS(k,q,s)  (uint32_t)(-(1UL<<(32-k))),q,s,(k-s)
+// state[] seeds must be >= 2^(32-k)
+#define QT_DEFAULT_SEED 128
+
+// period ~ 2^57
+// N.B. seed with: state[0] > 7, state[1] > 15
+static uint32_t lfsr57(uint32_t state[2]) {
+  state[0] = quickTaus(state[0], QT_PARAMS(29, 2,18) );
+  state[1] = quickTaus(state[1], QT_PARAMS(28, 9,14) );
+  return state[0] ^ state[1];
+}
+
+// period ~ 2^88
+// N.B. seed with: state[0] > 1, state[1] > 7, state[2] > 15
+static uint32_t lfsr88(uint32_t state[3]) {
+  state[0] = quickTaus(state[0], QT_PARAMS(31,13,12) );
+  state[1] = quickTaus(state[1], QT_PARAMS(29, 2, 4) );
+  state[2] = quickTaus(state[2], QT_PARAMS(28, 3,17) );
+  return state[0] ^ state[1] ^ state[2];
+}
+
+// period ~2^113
+// N.B. seed with: state[0] > 1, state[1] > 7, state[2] > 15, state[3] > 127
+static uint32_t lfsr113(uint32_t state[4]) {
+  // Alternative values of the QT_PARAMS 's' are listed in table 1 of:
+  // Tables Of Maximally Equidistributed Combined LFSR Generators: Pierre L'ecuyer
+  // www.ams.org/mcom/1999-68-225/S0025-5718-99-01039-X/S0025-5718-99-01039-X.pdf
+  state[0] = quickTaus(state[0], QT_PARAMS(31, 6,18) );
+  state[1] = quickTaus(state[1], QT_PARAMS(29, 2, 2) );
+  state[2] = quickTaus(state[2], QT_PARAMS(28,13, 7) );
+  state[3] = quickTaus(state[3], QT_PARAMS(25, 3,13) );
+  return state[0] ^ state[1] ^ state[2] ^ state[3];
+}
+
+static inline void sleepUntil(size_t numBits, client interface random_pool rpi) {
+  timer tmr;
+  uint32_t time;
+  tmr :> time;
+  time += rpi.timeUntil(numBits);
+  tmr when timerafter(time) :> void;
+}
+
+static size_t perturbe(uint32_t state[prngSize], static const size_t prngSize,
+                       size_t numBits, size_t& perturbeIndex, client interface random_pool rpi) {
+
+  // Truncate large numbers.
+  const size_t maxBits =  prngSize * (sizeof(uint32_t)*8);
+  if (numBits > maxBits)
+    numBits = maxBits;
+
+  // Initialise state access variables, we will update them in the loop.
+  size_t bitsInserted = 0; // What the caller wants to know.
+  // These three variables track where 'perturbeIndex' needs to be set to.
+  size_t index = perturbeIndex / (sizeof(uint32_t)*8);
+  size_t bitPos = perturbeIndex % (sizeof(uint32_t)*8);
+  size_t inserted = 0;
+
+  while (numBits) {
+    size_t tailBits = (sizeof(uint32_t)*8) - bitPos;
+    if (tailBits > numBits)
+      tailBits = numBits;
+
+    inserted = rpi.insert(state[index], bitPos, tailBits);
+    if (state[index] < QT_DEFAULT_SEED) {
+      // N.B. The value of the state must be >= 2^(32-k) viz 'QT_DEFAULT_SEED'
+      //      But the rpi pool may be empty.
+      state[index] ^= 0xffffffff; // Will this break our PRNG?
+    }
+    bitsInserted += inserted;
+    numBits -= inserted;
+
+    if (numBits &&               // More to do.
+        inserted == tailBits) {  // The pool is not empty.
+      // We need to move onto the next state[] value.
+      ++index;
+      if (index == prngSize)
+        index = 0;
+      bitPos = 0;
+    }
+    // else index, bitPos, inserted give where we got up to.
+  }
+
+  perturbeIndex = (index * (sizeof(uint32_t)*8)) + bitPos + inserted;
+  return bitsInserted;
+}
+
+[[distributable]]
+void random_prng_server(server interface random_prng prngi, client interface random_pool rpi,
+                        static const PrngSize prngSize, uint32_t (&?seed)[prngSize]) {
+
+  xassert(prngSize >= prng57 && prngSize <= prng113); // "Invalid prngSize".
+
+  size_t perturbeIndex = 0; // Track the next bit to be peturbed.
+  uint32_t state[prngSize]; // Can't initialise distributable variables. Why not?
+  if (!isnull(seed)) {
+    for (int i=0; i<prngSize; ++i)
+      xassert(seed[i] >= QT_DEFAULT_SEED); // "Invalid seed".
+    memcpy(state, seed, prngSize * sizeof(uint32_t));
+  }
+  else {
+    memset(state, QT_DEFAULT_SEED, prngSize * sizeof(uint32_t));
+  }
+
+  while(1) {
+    select {
+      case prngi.value(uint32_t values[n], size_t n) :
+        switch (prngSize) {
+          case prng57:
+            for (size_t i = 0; i < n; ++i)
+              values[i] = lfsr57(state);
+            break;
+          case prng88:
+            for (size_t i = 0; i < n; ++i)
+              values[i] = lfsr88(state);
+            break;
+          case prng113:
+            for (size_t i = 0; i < n; ++i)
+              values[i] = lfsr113(state);
+            break;
+        }
+        break;
+
+      case prngi.perturbe_nonBlocking(size_t numBits) -> size_t bitsUsed:
+        bitsUsed = perturbe(state, prngSize, numBits, perturbeIndex, rpi);
+        break;
+
+      case prngi.perturbe_blocking(size_t numBits) -> size_t bitsUsed:
+        bitsUsed = numBits;
+        while (numBits) {
+          numBits -= perturbe(state, prngSize, numBits, perturbeIndex, rpi);
+          if (numBits)
+            sleepUntil(numBits, rpi); // N.B. Only one clients wanting to block.
+        }
+        break;
+
+      case prngi.perturbe_halfAvailableBits() -> size_t bitsUsed:
+        bitsUsed = rpi.available() / 2; // We round down, so we can never use all bits.
+        (void) perturbe(state, prngSize, bitsUsed, perturbeIndex, rpi);
+        break;
+
+      case prngi.release():
+        return;
+    }
+  }
+}
diff --git a/lib_random/src/true_random.xc b/lib_random/src/true_random.xc
deleted file mode 100644
index 7dbc852..0000000
--- a/lib_random/src/true_random.xc
+++ /dev/null
@@ -1,48 +0,0 @@
-#include <platform.h>
-#include <stdio.h>
-#include <xs1.h>
-#include <xclib.h>
-#include "random.h"
-
-#define MIN_RANDOM_BITS 8
-
-static void inline ro_on() {
-    setps(0x60B, 2);
-}
-
-static void inline ro_off() {
-    setps(0x60B, 0);
-}
-
-
-
-#define TIME_FOR_ONE_BIT 20000
-static int last_time = 0;
-
-void random_true_init() {
-    asm("gettime %0" : "=r" (last_time));
-    ro_on();
-}
-
-{uint32_t,int32_t} random_true_get_bits() {
-    int time, ro;
-
-    ro_off();
-    asm("nop");
-    asm("nop");
-    asm("nop");
-    asm("nop");
-    ro = getps(0x70B);
-    asm("gettime %0" : "=r" (time));
-    ro_on();
-    
-    if (((unsigned)(time - last_time)) > TIME_FOR_ONE_BIT) {
-        last_time = time;
-        return {1, ro & 1};
-    }
-    return {0, last_time + TIME_FOR_ONE_BIT};
-}
-
-void random_true_uninit() {
-    ro_off();
-}
diff --git a/test/random/Makefile b/test/random/Makefile
new file mode 100644
index 0000000..b0ceab1
--- /dev/null
+++ b/test/random/Makefile
@@ -0,0 +1,14 @@
+TARGET = SLICEKIT-L16
+APP_NAME =
+USED_MODULES = lib_random
+
+XCC_FLAGS = -Os -g
+#XCC_FLAGS += -save-temps -v
+
+# We will be testing the deprecated interface...
+RANDOM_ENABLE_HW_SEED=1
+
+VERBOSE = 0
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/test/random/expected.output b/test/random/expected.output
new file mode 100644
index 0000000..e22e136
--- /dev/null
+++ b/test/random/expected.output
@@ -0,0 +1,4 @@
+test-3 done.
+test-2 done.
+test-0 done.
+test-1 done.
diff --git a/test/random/src/test.xc b/test/random/src/test.xc
new file mode 100755
index 0000000..6ba3ec1
--- /dev/null
+++ b/test/random/src/test.xc
@@ -0,0 +1,130 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <platform.h>
+#include "random.h"
+
+/////////////////////////////////////////////////////////
+// First some unit testing boiler plate
+interface checker {
+  void str(const char str[100]);
+  void release();
+};
+static void checkerServer(server interface checker si[n], static const size_t n, uint32_t timeout) {
+  // We will release when the last client has released us.
+  // All clients have implicitly claimed us, set the 'n' lowest bits.
+  if (n > 32) {
+    fprintf(stderr, "Error checkerServer: The maximum number of clients is 32\n");
+    return;
+  }
+  uint32_t activeClients = (1ULL<<n) - 1;
+
+  // Attempt to spot hung tests.
+  timer tmr;
+  uint32_t start;
+  tmr :> start;
+
+  while(1){
+    select{
+      case si[unsigned id].str(const char str[100]) :
+        char local[100];
+        memcpy(local,str,100);
+        fprintf(stderr, "%s\n", local);
+        break;
+      case si[unsigned id].release():
+        activeClients &= ~(1UL << id);
+        if (!activeClients)
+          return;
+        break;
+      case  tmr when timerafter(start + timeout) :> void:
+        fprintf(stderr, "Error checkerServer: timout after %d tick, activeClients mask=0x%X\n", timeout, activeClients);
+        exit(1);
+        break;
+    }
+  }
+}
+
+#define INFO(ci, ...) \
+  do { \
+    char _checker_buff[100]; \
+    snprintf(_checker_buff, 100, __VA_ARGS__); \
+    ci.str(_checker_buff); \
+  } while(0)
+
+#define CHECK(c, ci, ...) \
+  if (!(c)) INFO(ci, __VA_ARGS__)
+
+/////////////////////////////////////////////////////////
+
+typedef union {
+  uint32_t word[2];
+  uint8_t byte[8];
+} Bytes;
+
+
+void test(client interface checker ci, int id) {
+
+  // Check '0' is valid.
+  random_generator_t gen1 = random_create_generator_from_seed(0);
+  unsigned v1 = random_get_random_number(gen1);
+  CHECK( v1, ci, "test-%d unexpexted zero returned", id );
+  Bytes b1 = {{0,0}};
+  random_get_random_bytes(gen1, b1.byte, 5);
+  // simple checks of the values returned...
+  CHECK( b1.word[0] && b1.word[1], ci, "test-%d unexpexted zero returned, %#08X%08x", id, b1.word[0], b1.word[1] );
+  CHECK( (b1.word[1] & 0xffffff00) == 0, ci, "test-%d too many bytes read, %#08X%08x", id, b1.word[0], b1.word[1] );
+  // We do not test for 'out of bounds array access'
+  // random_get_random_bytes(gen1, b1.byte, 11);
+
+  // Check we get a different set of values.
+  random_generator_t gen2 = random_create_generator_from_seed(0x12345678);
+  unsigned v2 = random_get_random_number(gen2);
+  CHECK( v2 != v1, ci, "test-%d unexpexted same value", id );
+  Bytes b2 = {{0,0}};
+  random_get_random_bytes(gen2, b2.byte, 5);
+  CHECK( b2.word[0] != b1.word[0] && b2.word[1] != b1.word[1], ci, "unexpexted same bytes", id );
+
+  // We should get the same output as the first block.
+  random_generator_t gen3 = random_create_generator_from_seed(0);
+  unsigned v3 = random_get_random_number(gen3);
+  CHECK( v3 == v1, ci, "test-%d unexpexted different value", id );
+  Bytes b3 = {{0,0}};
+  random_get_random_bytes(gen3, b3.byte, 5);
+  CHECK( b3.word[0] == b1.word[0] && b3.word[1] == b1.word[1], ci, "unexpexted different bytes", id );
+
+  // All gernators are independant.
+  v1 = random_get_random_number(gen1);
+  v2 = random_get_random_number(gen2);
+  v3 = random_get_random_number(gen3);
+  CHECK( v2 != v1, ci, "test-%d unexpexted same value", id );
+  CHECK( v3 == v1, ci, "test-%d unexpexted different value", id );
+
+  Bytes zero = {{0,0}};
+  random_get_random_bytes(gen1, zero.byte, 0);
+  CHECK( !zero.word[0] && !zero.word[1], ci, "unexpexted bytes read", id );
+
+  // The following function is deprecated but still tested.
+  // We have add 'RANDOM_ENABLE_HW_SEED=1' to the Makefile.
+  // The build will generate a warning... which we ignore.
+  random_generator_t gen4 = random_create_generator_from_hw_seed();
+  // No delay needed.
+  random_generator_t gen5 = random_create_generator_from_hw_seed();
+  CHECK( gen4 != gen5, ci, "test-%d same hw seed generator", id );
+
+  INFO(ci, "test-%d done.", id);
+  ci.release();
+}
+
+int main() {
+  interface checker i[4];
+  par {
+    on tile[0] : checkerServer(i, 4, 100000);
+    on tile[0] : test(i[0], 0);
+    on tile[0] : test(i[1], 1);
+    on tile[1] : test(i[2], 2);
+    on tile[1] : test(i[3], 3);
+  }
+  return 0; // failure;
+}
diff --git a/test/random_bit/Makefile b/test/random_bit/Makefile
new file mode 100755
index 0000000..ef987ff
--- /dev/null
+++ b/test/random_bit/Makefile
@@ -0,0 +1,18 @@
+TARGET = SLICEKIT-L16
+APP_NAME =
+USED_MODULES = lib_random
+
+XCC_FLAGS = -Os -g
+#XCC_FLAGS += -save-temps -v
+
+# RANDOM_ENABLE_HW_SEED must either:
+#    not be declared at all
+#    or if it is, take the value '0'.
+# We chose the second option here as an example, other tests do not declare it at all.
+# N.B. We expect random_deprecated.c not to be built.
+RANDOM_ENABLE_HW_SEED=0
+
+VERBOSE = 0
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/test/random_bit/expected.output b/test/random_bit/expected.output
new file mode 100644
index 0000000..1364fd4
--- /dev/null
+++ b/test/random_bit/expected.output
@@ -0,0 +1,6 @@
+testClaimSimple-1 done.
+testClaimSimple-0 done.
+testClaimingParallel-1 done.
+testClaimingParallel-0 done.
+testBit-1 done.
+testBit-0 done.
diff --git a/test/random_bit/src/test.xc b/test/random_bit/src/test.xc
new file mode 100755
index 0000000..1776e6b
--- /dev/null
+++ b/test/random_bit/src/test.xc
@@ -0,0 +1,199 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <platform.h>
+#include "random_bit.h"
+
+/////////////////////////////////////////////////////////
+// First some unit testing boiler plate
+interface checker {
+  void str(const char str[100]);
+  void release();
+};
+static void checkerServer(server interface checker si[n], static const size_t n, uint32_t timeout) {
+  // We will release when the last client has released us.
+  // All clients have implicitly claimed us, set the 'n' lowest bits.
+  if (n > 32) {
+    fprintf(stderr, "Error checkerServer: The maximum number of clients is 32\n");
+    return;
+  }
+  uint32_t activeClients = (1ULL<<n) - 1;
+
+  // Attempt to spot hung tests.
+  timer tmr;
+  uint32_t start;
+  tmr :> start;
+
+  while(1){
+    select{
+      case si[unsigned id].str(const char str[100]) :
+        char local[100];
+        memcpy(local,str,100);
+        fprintf(stderr, "%s\n", local);
+        break;
+      case si[unsigned id].release():
+        activeClients &= ~(1UL << id);
+        if (!activeClients)
+          return;
+        break;
+      case  tmr when timerafter(start + timeout) :> void:
+        fprintf(stderr, "Error checkerServer: timout after %d tick, activeClients mask=0x%X\n", timeout, activeClients);
+        exit(1);
+        break;
+    }
+  }
+}
+
+#define INFO(ci, ...) \
+  do { \
+    char _checker_buff[100]; \
+    snprintf(_checker_buff, 100, __VA_ARGS__); \
+    ci.str(_checker_buff); \
+  } while(0)
+
+#define CHECK(c, ci, ...) \
+  if (!(c)) INFO(ci, __VA_ARGS__)
+
+/////////////////////////////////////////////////////////
+
+// Use 'TIME_FOR_ONE_BIT' from random_impl.h
+#include "../../lib_random/src/random_impl.h"
+#define UNCERTAINTY        200
+
+static void sleep(uint32_t n) {
+  timer tmr;
+  uint32_t now;
+  tmr :> now;
+  tmr when timerafter(now+n) :> void;
+}
+
+void testClaimSimple(client interface checker ci, int id) {
+  CHECK( random_bit_claim() == 1, ci, "testClaimSimple-%d step 1", id );
+  random_bit_release();
+  CHECK( random_bit_claim() == 1, ci, "testClaimSimple-%d step 2", id );
+  CHECK( random_bit_claim() == 0, ci, "testClaimSimple-%d step 3", id );
+  random_bit_release();
+  INFO(ci, "testClaimSimple-%d done.", id);
+  ci.release();
+}
+
+static int canClaim(uint32_t n) {
+  sleep(n);
+  if (random_bit_claim()) {
+    sleep(100); // keep hold for a while.
+    random_bit_release();
+    return 1;
+  }
+  return 0;
+}
+
+void testClaimingParallel(client interface checker ci, int id) {
+  int ret[6];
+  par {
+    // Only one logical core on a tile can claim.
+    ret[0] = canClaim(0);
+    ret[1] = canClaim(0);
+    ret[2] = canClaim(0);
+    // Once released (after 100), another logical core can claim (after 200)
+    ret[3] = canClaim(200);
+    ret[4] = canClaim(200);
+    ret[5] = canClaim(200);
+  }
+  CHECK( ret[0]+ret[1]+ret[2] == 1, // One of them succeeds.
+         ci, "testClaimingParallel-%d now", id );
+  CHECK( ret[3]+ret[4]+ret[5] == 1, // One of them succeeds.
+         ci, "testClaimingParallel-%d delayed", id );
+  INFO(ci, "testClaimingParallel-%d done.", id);
+  ci.release();
+}
+
+void testBit_notReady(client interface checker ci, int id, int step, uint32_t expectedTime) {
+  uint32_t time;
+  CHECK( random_bit(time) == 0,
+         ci, "testBit-%d step 1 should not be ready", id );
+  CHECK( expectedTime-UNCERTAINTY < time &&
+         expectedTime+UNCERTAINTY > time,
+         ci,"testBit-%d step %d expected time %d +- %d, acutal time %d\n", id, step, expectedTime, UNCERTAINTY, time);
+}
+
+void testBit_ready(client interface checker ci, int id, int step) {
+  uint32_t bit;
+  CHECK( random_bit(bit) == 1,
+         ci, "testBit-%d step %d should be ready", id ,step );
+  // We don't currently CHECK the bit - need to feed this into the simulator's "getps(0x70B)".
+}
+
+void testBit(client interface checker ci, int id) {
+  // We don't need to call random_bit_claim() ... even if it is bad style :0
+  timer tmr;
+  uint32_t t;
+
+  random_bit_start();
+  tmr :> t;
+  // Check at start.
+  t += TIME_FOR_ONE_BIT; // We expect it to be ready in 'TIME_FOR_ONE_BIT' ticks.
+  testBit_notReady(ci, id, 1, t);
+
+  sleep(TIME_FOR_ONE_BIT/2);
+
+  // Check at half way point.
+  testBit_notReady(ci, id, 2, t);
+
+  sleep(TIME_FOR_ONE_BIT/2);
+
+  // Check at ready time.
+  testBit_ready(ci, id, 3);
+  tmr :> t; // Time till next bit from when we read previous bit.
+  t += TIME_FOR_ONE_BIT; // We expect next bit ready in 'TIME_FOR_ONE_BIT' ticks from now.
+
+  // Check next bit is not ready.
+  testBit_notReady(ci, id, 4, t);
+
+  // Sleep extra long.
+  sleep(TIME_FOR_ONE_BIT*2);
+
+  // We expect only one bit ready.
+  testBit_ready(ci, id, 5);
+  tmr :> t; // Time till next bit from when we read previous bit.
+  t += TIME_FOR_ONE_BIT; // We expect next bit ready in 'TIME_FOR_ONE_BIT' ticks from now.
+
+  // Check next bit is not ready.
+  testBit_notReady(ci, id, 6, t);
+
+  // stopping and starting will reset the time until ready.
+  sleep(TIME_FOR_ONE_BIT*2);
+  random_bit_stop();
+  random_bit_start();
+  tmr :> t;
+  t += TIME_FOR_ONE_BIT; // We expect it to be ready in 'TIME_FOR_ONE_BIT' ticks.
+  testBit_notReady(ci, id, 7, t);
+
+  random_bit_stop();
+  INFO(ci, "testBit-%d done.", id);
+  ci.release();
+}
+
+int main() {
+  interface checker i[6];
+  par {
+    on tile[0] : checkerServer(i,6, TIME_FOR_ONE_BIT*6);
+
+    on tile[0] : {
+      testClaimSimple(i[0], 0);
+      // Followed by.
+      testClaimingParallel(i[1] ,0);
+    }
+    on tile[0] : testBit(i[2], 0);
+
+    // The tests on each tile are independant.
+    on tile[1] : {
+      testClaimSimple(i[3], 1);
+      // Followed by.
+      testClaimingParallel(i[4], 1);
+    }
+    on tile[1] : testBit(i[5], 1);
+  }
+  return 0;
+}
\ No newline at end of file
diff --git a/test/random_pool/Makefile b/test/random_pool/Makefile
new file mode 100644
index 0000000..fbb3bc9
--- /dev/null
+++ b/test/random_pool/Makefile
@@ -0,0 +1,11 @@
+TARGET = SLICEKIT-L16
+APP_NAME =
+USED_MODULES = lib_random
+
+XCC_FLAGS = -Os -g
+#XCC_FLAGS += -save-temps -v
+
+VERBOSE = 0
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/test/random_pool/expected.output b/test/random_pool/expected.output
new file mode 100644
index 0000000..8717b1c
--- /dev/null
+++ b/test/random_pool/expected.output
@@ -0,0 +1,6 @@
+testPool-3 done.
+testPool-4 done.
+testPool-5 done.
+testPool-0 done.
+testPool-1 done.
+testPool-2 done.
diff --git a/test/random_pool/src/test.xc b/test/random_pool/src/test.xc
new file mode 100755
index 0000000..4c0be42
--- /dev/null
+++ b/test/random_pool/src/test.xc
@@ -0,0 +1,201 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <platform.h>
+#include "random_pool.h"
+
+/////////////////////////////////////////////////////////
+// First some unit testing boiler plate
+interface checker {
+  void str(const char str[100]);
+  void release();
+};
+static void checkerServer(server interface checker si[n], static const size_t n, uint32_t timeout) {
+  // We will release when the last client has released us.
+  // All clients have implicitly claimed us, set the 'n' lowest bits.
+  if (n > 32) {
+    fprintf(stderr, "Error checkerServer: The maximum number of clients is 32\n");
+    return;
+  }
+  uint32_t activeClients = (1ULL<<n) - 1;
+
+  // Attempt to spot hung tests.
+  timer tmr;
+  uint32_t start;
+  tmr :> start;
+
+  while(1){
+    select{
+      case si[unsigned id].str(const char str[100]) :
+        char local[100];
+        memcpy(local,str,100);
+        fprintf(stderr, "%s\n", local);
+        break;
+      case si[unsigned id].release():
+        activeClients &= ~(1UL << id);
+        if (!activeClients)
+          return;
+        break;
+      case  tmr when timerafter(start + timeout) :> void:
+        fprintf(stderr, "Error checkerServer: timout after %d tick, activeClients mask=0x%X\n", timeout, activeClients);
+        exit(1);
+        break;
+    }
+  }
+}
+
+#define INFO(ci, ...) \
+  do { \
+    char _checker_buff[100]; \
+    snprintf(_checker_buff, 100, __VA_ARGS__); \
+    ci.str(_checker_buff); \
+  } while(0)
+
+#define CHECK(c, ci, ...) \
+  if (!(c)) INFO(ci, __VA_ARGS__)
+
+/////////////////////////////////////////////////////////
+
+// Use 'TIME_FOR_ONE_BIT' from random_impl.h
+#include "../../lib_random/src/random_impl.h"
+#define DELAY              500
+
+static void delay() {
+  timer tmr;
+  uint32_t now;
+  tmr :> now;
+  tmr when timerafter(now+DELAY) :> void;
+}
+
+void testPool_timeuntil(client interface checker ci, int id,
+                        client interface random_pool rpi, size_t numBits, size_t poolBits) {
+  uint32_t time = rpi.timeUntil(numBits);
+
+  // How many bit are we waiting for.
+  size_t reportedBits = (numBits > rpi.capacity())? rpi.capacity() : numBits;
+  reportedBits = (reportedBits<poolBits)? 0 : reportedBits - poolBits;
+  uint32_t expected = TIME_FOR_ONE_BIT * reportedBits; // We know how it is caluclated!
+
+  CHECK( expected == time,
+         ci,"testPool-%d %d bits : expected time %d, acutal time %d\n", id, numBits, expected, time);
+}
+
+void testPool(client interface checker ci, int id,
+              client interface random_pool rpi) {
+
+  size_t expectedCapacity = (id<3)? 7 : 15; // See random_pool_server(..., bitsToPoolSize).
+  CHECK( rpi.capacity() == expectedCapacity,
+        ci, "testPool-%d capacity %d not %d", id, rpi.capacity(), expectedCapacity );
+
+  CHECK( rpi.available() == 0,
+        ci, "testPool-%d expected 0, actual %d bits", id, rpi.available() );
+
+  timer tmr;
+  uint32_t now;
+  tmr :> now;
+  testPool_timeuntil(ci, id, rpi, 0, 0);
+  testPool_timeuntil(ci, id, rpi, 1, 0);
+  testPool_timeuntil(ci, id, rpi, 2, 0);
+  testPool_timeuntil(ci, id, rpi, 99, 0);
+
+  tmr when timerafter(now + TIME_FOR_ONE_BIT) :> void;
+  CHECK( rpi.available() == 1,
+        ci, "testPool-%d expected 1, actual %d bits", id, rpi.available() );
+
+  // Retest, but the periods will be reduced as we have a bit in the pool
+  testPool_timeuntil(ci, id, rpi, 0, 1);
+  testPool_timeuntil(ci, id, rpi, 1, 1);
+  testPool_timeuntil(ci, id, rpi, 2, 1);
+  testPool_timeuntil(ci, id, rpi, 99, 1);
+
+  tmr when timerafter(now + TIME_FOR_ONE_BIT*2) :> void;
+  CHECK( rpi.available() == 2,
+        ci, "testPool-%d expected 2, actual %d bits", id, rpi.available() );
+
+  delay(); // Allow all cores to check the pool before continuing.
+
+  // Then allow one core to plunder the pool.
+  if (id==0 || id==3) {
+    // Retest, but the periods will be reduced as we have 2 bits in the pool
+    testPool_timeuntil(ci, id, rpi, 0, 2);
+    testPool_timeuntil(ci, id, rpi, 1, 2);
+    testPool_timeuntil(ci, id, rpi, 2, 2);
+    testPool_timeuntil(ci, id, rpi, 99, 2);
+
+    uint32_t bits;
+    CHECK( rpi.insert(bits, 32, 1) == 0, // Outside of range.
+          ci, "testPool-%d incorrectly inserted bit32", id);
+    CHECK( rpi.available() == 2,
+          ci, "testPool-%d 2-0=2, actual %d bits", id, rpi.available() );
+
+    CHECK( rpi.insert(bits, 31, 5) == 1, // Truncate to last bit.
+          ci, "testPool-%d expected bit31 to be filled", id);
+    // We don't currently CHECK the bit - need to feed this into the simulator's "getps(0x70B)".
+    CHECK( rpi.available() == 1,
+          ci, "testPool-%d 2-1=1, actual %d bits", id, rpi.available() );
+
+    CHECK( rpi.insert(bits, 0, 999) == 1, // Request far too many bits!
+          ci, "testPool-%d expected only bit0 to be filled", id);
+    // We don't currently CHECK the bit - need to feed this into the simulator's "getps(0x70B)".
+    CHECK( rpi.available() == 0,
+          ci, "testPool-%d 1-1=0, actual %d bits", id, rpi.available() );
+
+    CHECK( rpi.insert(bits, 0, 1) == 0, // None available.
+          ci, "testPool-%d expected no bits to be filled", id);
+    CHECK( rpi.available() == 0,
+          ci, "testPool-%d 0-0=0, actual %d bits", id, rpi.available() );
+
+    // Retest now the pool is empty.
+    testPool_timeuntil(ci, id, rpi, 0, 0);
+    testPool_timeuntil(ci, id, rpi, 1, 0);
+    testPool_timeuntil(ci, id, rpi, 2, 0);
+    testPool_timeuntil(ci, id, rpi, 99, 0);
+  }
+  else {
+    // Wait for the pool to be plundered.
+    delay();
+
+    // The bit will have been taken by id 0.
+    CHECK( rpi.available() == 0,
+          ci, "testPool-%d pool contains %d bits", id, rpi.available() );
+    uint32_t bits;
+    CHECK( rpi.insert(bits, 32, 1) == 0, // Outside of range.
+          ci, "testPool-%d bit32 expected no bits to be filled", id);
+
+    CHECK( rpi.insert(bits, 31, 5) == 0, // Truncate to last bit.
+          ci, "testPool-%d bit31 expected no bits to be filled", id);
+
+    CHECK( rpi.insert(bits, 0, 999) == 0, // Request far too many bits!
+          ci, "testPool-%d bit0 expected no bits to be filled", id);
+
+    CHECK( rpi.insert(bits, 0, 1) == 0, // None available.
+          ci, "testPool-%d expected no bits to be filled", id);
+  }
+  rpi.release();
+
+  INFO(ci, "testPool-%d done.", id);
+  ci.release();
+}
+
+int main() {
+  interface checker i[6];
+  interface random_pool rpi_0[3];
+  interface random_pool rpi_1[3];
+
+  par {
+    on tile[0] : checkerServer(i, 6, TIME_FOR_ONE_BIT*3);
+
+    on tile[0] : random_pool_server(rpi_0, 3, bitsToPoolSize(3)); // Rounded to 8.
+    on tile[0] : testPool(i[0], 0, rpi_0[0]);
+    on tile[0] : testPool(i[1], 1, rpi_0[1]);
+    on tile[0] : testPool(i[2], 2, rpi_0[2]);
+
+    on tile[1] : random_pool_server(rpi_1, 3, bitsToPoolSize(11)); // Rounded to 16.
+    on tile[1] : testPool(i[3], 3, rpi_1[0]);
+    on tile[1] : testPool(i[4], 4, rpi_1[1]);
+    on tile[1] : testPool(i[5], 5, rpi_1[2]);
+  }
+  return 0; // failure;
+}
diff --git a/test/random_prng/Makefile b/test/random_prng/Makefile
new file mode 100644
index 0000000..aee3fe4
--- /dev/null
+++ b/test/random_prng/Makefile
@@ -0,0 +1,13 @@
+TARGET = STARTKIT
+APP_NAME =
+USED_MODULES = lib_random
+
+XCC_FLAGS = -Os -g
+
+#XCC_FLAGS += -save-temps -v
+
+XCORE_ARM_PROJECT = 0
+VERBOSE = 0
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/test/random_prng/expected.output b/test/random_prng/expected.output
new file mode 100644
index 0000000..c693646
--- /dev/null
+++ b/test/random_prng/expected.output
@@ -0,0 +1,16 @@
+Task-pool-client0 available=0 capacity=15
+Task-pool-client1 available=0 capacity=15
+subtask-A raw -     16C800B3 279E25
+subtask-A half 0     3589669D 4AF41D37
+Task-pool-client1 available=0 capacity=15
+Exit Task-pool-client1
+subtask-A nonblocking 2     7461669 8ABA72F6
+subtask-A blocking 1     8EDBF15A 2C5DF060
+Exit subtask-A
+subtask-B raw -     505F0BD9 35375D85
+subtask-B half 0     783D9EC4 B0C1B1A0
+subtask-B nonblocking 2     47AE1A01 95AB4431
+subtask-B blocking 1     20AB0D85 B0E484A6
+Exit subtask-B
+Exit Task-pool-client0
+Exit Task-pool-server
diff --git a/test/random_prng/src/test.xc b/test/random_prng/src/test.xc
new file mode 100755
index 0000000..65b9eee
--- /dev/null
+++ b/test/random_prng/src/test.xc
@@ -0,0 +1,77 @@
+
+#include "random_prng.h"
+#include <stdio.h>
+#include <xs1.h>
+
+#define PRINT(...) printf(__VA_ARGS__)
+//#define PRINT(...)
+
+void test(const char*unsafe name, client interface random_prng prngi) {
+  uint32_t values[2];
+  prngi.value(values, 2);
+  PRINT("%s raw -     %X %X\n",name, values[0], values[1]);
+
+  size_t done = prngi.perturbe_halfAvailableBits();
+  prngi.value(values, 2);
+  PRINT("%s half %d     %X %X\n", name, done, values[0], values[1]);
+
+  done = prngi.perturbe_nonBlocking(2);
+  prngi.value(values, 2);
+  PRINT("%s nonblocking %d     %X %X\n", name, done, values[0], values[1]);
+
+  done = prngi.perturbe_blocking(1);
+  prngi.value(values, 2);
+  PRINT("%s blocking %d     %X %X\n", name, done, values[0], values[1]);
+
+  // Client prngi is no longer wanted.
+  prngi.release(); // This will allow the random_prng_server() to exit too.
+  PRINT("Exit %s\n", name);
+}
+
+int main() {
+  interface random_pool rpi[2];
+  par {
+    // Task-pool-server
+    random_pool_server(rpi, 2, bitsToPoolSize(11));
+
+    // Task-pool-client0 with subtasks.
+    {
+      PRINT("Task-pool-client0 available=%d capacity=%d\n", rpi[0].available(), rpi[0].capacity());
+      uint32_t seed[prng57] = {1234,5678};
+      interface random_prng prngi;
+      // subtask-A.
+      par {
+        [[distribute]]
+        random_prng_server(prngi, rpi[0], prng57, seed);
+        test("subtask-A", prngi);
+      }
+      // Follow with a sequential subtask-B.
+      // We can reuse the prngi interface object to start a new server & client.
+      // N.B. BUT ONLY IF THE INTERFACE IS THE SAME TYPE - both 'distribute' or not!!
+      par {
+        [[distribute]]
+        random_prng_server(prngi, rpi[0], prng113, null); // Use the default seed
+        test("subtask-B", prngi);
+      }
+      // Client rpi[0] is no longer wanted.
+      rpi[0].release(); // This will allow the random_pool_server() to exit too.
+      PRINT("Exit Task-pool-client0\n");
+    }
+
+    // Task-pool-client1
+    {
+      PRINT("Task-pool-client1 available=%d capacity=%d\n", rpi[1].available(), rpi[1].capacity());
+      timer tmr;
+      uint32_t time;
+      tmr :> time;
+      tmr when timerafter(time+20000) :> void;
+      PRINT("Task-pool-client1 available=%d capacity=%d\n", rpi[1].available(), rpi[1].capacity());
+      // Client rpi[1] is no longer wanted.
+      rpi[1].release(); // This will allow the random_pool_server() to exit too.
+      PRINT("Exit Task-pool-client1\n");
+    }
+  }
+  PRINT("Exit Task-pool-server\n");
+  return 0;
+}
+
diff --git a/test/runtests.py b/test/runtests.py
new file mode 100755
index 0000000..d422f09
--- /dev/null
+++ b/test/runtests.py
@@ -0,0 +1,9 @@
+#!/usr/bin/env python
+import xmostest, sys, subprocess
+
+if __name__ == "__main__":
+    xmostest.init()
+    xmostest.register_group("lib_random", "lib_random_tests", "lib_random library tests", "Tests random_bit.h, random_pool.h, random_prng.h and random.h")
+    xmostest.runtests()
+    xmostest.finish()
+
diff --git a/test/test_random.py b/test/test_random.py
new file mode 100755
index 0000000..845222b
--- /dev/null
+++ b/test/test_random.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import xmostest
+
+def runtest():
+    resources = xmostest.request_resource("xsim")
+
+    tester = xmostest.ComparisonTester(open('random/expected.output'),
+                                       'lib_random',
+                                       'lib_random_tests',
+                                       'random', {})
+
+    xmostest.run_on_simulator(resources['xsim'],
+                              'random/bin/random.xe',
+                              tester=tester)
+
diff --git a/test/test_random_bit.py b/test/test_random_bit.py
new file mode 100755
index 0000000..d593f10
--- /dev/null
+++ b/test/test_random_bit.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import xmostest
+
+def runtest():
+    resources = xmostest.request_resource("xsim")
+
+    tester = xmostest.ComparisonTester(open('random_bit/expected.output'),
+                                       'lib_random',
+                                       'lib_random_tests',
+                                       'random_bit', {})
+
+    xmostest.run_on_simulator(resources['xsim'],
+                              'random_bit/bin/random_bit.xe',
+                              tester=tester)
+
diff --git a/test/test_random_pool.py b/test/test_random_pool.py
new file mode 100755
index 0000000..3781d9d
--- /dev/null
+++ b/test/test_random_pool.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import xmostest
+
+def runtest():
+    resources = xmostest.request_resource("xsim")
+
+    tester = xmostest.ComparisonTester(open('random_pool/expected.output'),
+                                       'lib_random',
+                                       'lib_random_tests',
+                                       'random_pool', {})
+
+    xmostest.run_on_simulator(resources['xsim'],
+                              'random_pool/bin/random_pool.xe',
+                              tester=tester)
+
diff --git a/test/test_random_prng.py b/test/test_random_prng.py
new file mode 100755
index 0000000..8fa443c
--- /dev/null
+++ b/test/test_random_prng.py
@@ -0,0 +1,15 @@
+#!/usr/bin/env python
+import xmostest
+
+def runtest():
+    resources = xmostest.request_resource("xsim")
+
+    tester = xmostest.ComparisonTester(open('random_prng/expected.output'),
+                                       'lib_random',
+                                       'lib_random_tests',
+                                       'random_prng', {})
+
+    xmostest.run_on_simulator(resources['xsim'],
+                              'random_prng/bin/random_prng.xe',
+                              tester=tester)
+

From f6237d03717c36e8fbb433975cb886ae65066913 Mon Sep 17 00:00:00 2001
From: robert lytton <robert@xmos.com>
Date: Thu, 23 Nov 2017 11:23:56 +0000
Subject: [PATCH 07/10] Add examples/dieharder for validating random_prng.h

Make random_prng_server(...,client interface random_pool ?rpi,...) optinal
---
 .../AN002xx_random_number_generation/Makefile |   1 -
 examples/dieharder/Makefile                   |  10 ++
 examples/dieharder/README                     |  11 ++
 examples/dieharder/src/gen.xc                 | 135 ++++++++++++++++++
 lib_random/api/random_prng.h                  |   4 +-
 lib_random/src/random_prng.xc                 |   2 +-
 test/random_prng/Makefile                     |   2 -
 7 files changed, 159 insertions(+), 6 deletions(-)
 create mode 100755 examples/dieharder/Makefile
 create mode 100644 examples/dieharder/README
 create mode 100755 examples/dieharder/src/gen.xc

diff --git a/examples/AN002xx_random_number_generation/Makefile b/examples/AN002xx_random_number_generation/Makefile
index 48cf165..b0101e3 100644
--- a/examples/AN002xx_random_number_generation/Makefile
+++ b/examples/AN002xx_random_number_generation/Makefile
@@ -3,7 +3,6 @@ APP_NAME =
 USED_MODULES = lib_random
 
 XCC_FLAGS = -O2 -g -Wunused -fxscope
-XCORE_ARM_PROJECT = 0
 VERBOSE = 0
 
 XMOS_MAKE_PATH ?= ../..
diff --git a/examples/dieharder/Makefile b/examples/dieharder/Makefile
new file mode 100755
index 0000000..8f7774b
--- /dev/null
+++ b/examples/dieharder/Makefile
@@ -0,0 +1,10 @@
+TARGET = STARTKIT
+APP_NAME =
+USED_MODULES = lib_random
+
+XCC_FLAGS = -Os -g -fcmdline-buffer-bytes=100
+#XCC_FLAGS += -save-temps -v
+
+
+XMOS_MAKE_PATH ?= ../..
+-include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/examples/dieharder/README b/examples/dieharder/README
new file mode 100644
index 0000000..41214db
--- /dev/null
+++ b/examples/dieharder/README
@@ -0,0 +1,11 @@
+This is a wrapper for testing the quality of the PRNG using dieharder.
+http://webhome.phy.duke.edu/~rgb/General/dieharder.php
+
+It is slow as it runs the random_prng.h library code under simulation.
+
+If this is a problem, copy the lfsr57(), lfsr88(), & lfsr113() functions
+into a host application and run nativly, viz test just the algorithm!
+
+The expected usage is:
+   axe --args bin/dieharder.xe -g prng57 -n -1 -o - -B | dieharder -g 200 -a
+(see dieharder.xe and dieharder help files for details)
diff --git a/examples/dieharder/src/gen.xc b/examples/dieharder/src/gen.xc
new file mode 100755
index 0000000..de67dfe
--- /dev/null
+++ b/examples/dieharder/src/gen.xc
@@ -0,0 +1,135 @@
+// Copyright (c) 2017, XMOS Ltd, All rights reserved
+
+// The expected usage is for validating against 'dieharder'
+// axe --args bin/dieharder.xe -g prng57 -n -1 -o - -B | dieharder -g 200 -a
+
+// We want raw stdio.h, not the safe version.
+#define UNSAFE_LIBC
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <xs1.h>
+#include "random_prng.h"
+
+static const char*unsafe prngString(PrngSize prng) {
+  unsafe {
+    switch (prng) {
+      case prng57: return "prng57";
+      case prng88: return "prng88";
+      case prng113: return "prng113";
+      default: return "prngInvalid";
+    }
+  }
+}
+
+unsigned readArgs(unsigned argC, char*unsafe argV[],
+             PrngSize& prng, unsigned& numValues, const char*unsafe& filename, unsigned& binary) {
+  unsigned found_g = 0;
+  unsigned found_n = 0;
+  unsigned found_o = 0;
+  binary = 0;
+
+  if (argC == 7 || argC == 8) {
+    for(unsigned i=1; i<argC; i+=2) {
+      if (strcmp(argV[i], "-B") == 0) {
+        binary = 1;
+        --i; // Hack the incrementor.
+      }
+      if (strcmp(argV[i], "-n") == 0) {
+        numValues = atoi(argV[i+1]);
+        found_n = 1;
+      }
+      else if (strcmp(argV[i], "-o") == 0) {
+        filename = argV[i+1];
+        found_o = 1;
+      }
+      else if (strcmp(argV[i], "-g") == 0) {
+        found_g = 1;
+        if (strcmp(argV[i+1], "prng57") == 0)
+          prng = prng57;
+        else if (strcmp(argV[i+1], "prng88") == 0)
+          prng = prng88;
+        else if (strcmp(argV[i+1], "prng113") == 0)
+          prng = prng113;
+        else
+          found_g = 0;
+      }
+    }
+  }
+  if (found_g && found_n && found_o && (argC == 7 || binary))
+    return 1;
+  if (!argC) {
+    printf ("Usage: Rebuild .xe with `-fcmdline-buffer-bytes=<value>` set\n");
+    printf ("       and make sure you pass commandline arg using `xsim --args ...` or `axe --args ...`\n");
+  }
+  else {
+    printf ("Usage: `axe --args %s -g <prng57|prng88|prng113> -n <numValues|-1> -o <outfile|-> [-B]`\n", argV[0]);
+    printf ("        -g <prng57|prng88|prng113> see random_prng.h and PrngSize for details;\n");
+    printf ("        -n <numValues|-1>          the number of 32bit values to generate, or -1 (with -B) for continuous;\n");
+    printf ("        -o <outfile|->             output file name, or '-' for stdout;\n");
+    printf ("        -B                         to turn on binary output, otherwise output will be in ASCII dieharder format.\n");
+  }
+  return 0;
+}
+
+FILE*unsafe openOutFile(const char*unsafe filename, unsigned numValues, unsigned prng, unsigned binary) {
+  FILE*unsafe fp = (strcmp(filename, "-") == 0) ? stdout :
+                                                  fopen(filename, binary? "wb":"w");
+  if (!fp)
+    printf ("Unable to open output file %s\n", filename);
+  else if (!binary) {
+    fprintf(fp, "#==================================================================\n");
+    fprintf(fp, "# generator random_prng.h %s seed=null\n", prngString(prng));
+    fprintf(fp, "#==================================================================\n");
+    fprintf(fp, "type: d\n");
+    fprintf(fp, "count: %u\n", numValues);
+    fprintf(fp, "numbit: 32\n");
+  }
+  return fp;
+}
+
+int main(unsigned argC, char*unsafe argV[argC]) {
+  PrngSize prng = 0;
+  unsigned numValues = 0;
+  const char*unsafe filename;
+  unsigned binary;
+  unsafe {
+    if (!readArgs(argC, argV, prng, numValues, filename, binary))
+      return 1;
+  }
+  FILE*unsafe fp = openOutFile(filename, numValues, prng, binary);
+
+  //interface random_pool rpi[1];
+  par {
+    //random_pool_server(rpi, 1, bitsToPoolSize(1)); // We wont be using it.
+    {
+      interface random_prng prngi;
+      par {
+        [[distribute]]
+        random_prng_server(prngi, null, prng57, null);
+        // random_prng_server(prngi, rpi[0], prng57, null);
+        {
+          // Client task.
+          while (numValues) {
+            enum{blkLen=1000};
+            uint32_t values[blkLen];
+            unsigned len = (blkLen < numValues)? blkLen : numValues;
+            prngi.value(values, len);
+            if (binary)
+              fwrite(values, len, sizeof(uint32_t), fp);
+            else
+              for (unsigned i=0; i < len; ++i)
+                fprintf(fp, "%10u\n", values[i]);
+            if (!binary || numValues != (unsigned)(-1))
+              numValues -= len;
+          }
+          fclose(fp);
+          prngi.release();
+        }
+      }
+      //rpi[0].release();
+    }
+  }
+  return 0;
+}
diff --git a/lib_random/api/random_prng.h b/lib_random/api/random_prng.h
index 83a22ec..f45b375 100755
--- a/lib_random/api/random_prng.h
+++ b/lib_random/api/random_prng.h
@@ -58,13 +58,13 @@ typedef enum {prng57=2, prng88=3, prng113=4} PrngSize;
  *      server-client pair with a unique seed.
  *
  * \param prngi     Server end of an `interface random_PRNG`.
- * \param rpi       Client end of an `interface random_pool`.
+ * \param rpi       Client end of an `interface random_pool`, null if perturbe_*() is never called.
  * \param prngSize  Either 'prng57', 'prng88' or 'prng113'.
  * \param seed      Optional seed for the PRNG (or null)
  *                  N.B. each seed[] entry must be > 127, the default value is 128.
  */
 [[distributable]]
-void random_prng_server(server interface random_prng prngi, client interface random_pool rpi,
+void random_prng_server(server interface random_prng prngi, client interface random_pool ?rpi,
                         static const PrngSize prngSize, uint32_t (&?seed)[prngSize]);
 
 #endif // __RANDOM_PRNG_H__
diff --git a/lib_random/src/random_prng.xc b/lib_random/src/random_prng.xc
index bf3d445..dbc5166 100755
--- a/lib_random/src/random_prng.xc
+++ b/lib_random/src/random_prng.xc
@@ -106,7 +106,7 @@ static size_t perturbe(uint32_t state[prngSize], static const size_t prngSize,
 }
 
 [[distributable]]
-void random_prng_server(server interface random_prng prngi, client interface random_pool rpi,
+void random_prng_server(server interface random_prng prngi, client interface random_pool ?rpi,
                         static const PrngSize prngSize, uint32_t (&?seed)[prngSize]) {
 
   xassert(prngSize >= prng57 && prngSize <= prng113); // "Invalid prngSize".
diff --git a/test/random_prng/Makefile b/test/random_prng/Makefile
index aee3fe4..526dc6f 100644
--- a/test/random_prng/Makefile
+++ b/test/random_prng/Makefile
@@ -3,10 +3,8 @@ APP_NAME =
 USED_MODULES = lib_random
 
 XCC_FLAGS = -Os -g
-
 #XCC_FLAGS += -save-temps -v
 
-XCORE_ARM_PROJECT = 0
 VERBOSE = 0
 
 XMOS_MAKE_PATH ?= ../..

From 3862bd60204cdafbde3a528c4a59e4f0c5304b35 Mon Sep 17 00:00:00 2001
From: Sam Chesney <samc@xmos.com>
Date: Wed, 15 Aug 2018 11:35:10 +0100
Subject: [PATCH 08/10] Add Jenkins pipeline

---
 Jenkinsfile | 43 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)
 create mode 100644 Jenkinsfile

diff --git a/Jenkinsfile b/Jenkinsfile
new file mode 100644
index 0000000..986ea58
--- /dev/null
+++ b/Jenkinsfile
@@ -0,0 +1,43 @@
+pipeline {
+  agent {
+    label 'x86&&macOS&&Apps'
+  }
+  environment {
+    VIEW = 'random'
+    REPO = 'lib_random'
+  }
+  options {
+    skipDefaultCheckout()
+  }
+  stages {
+    stage('Get view') {
+      steps {
+        prepareAppsSandbox("${VIEW}", "${REPO}")
+      }
+    }
+    stage('Library checks') {
+      steps {
+        xcoreLibraryChecks("${REPO}")
+      }
+    }
+    stage('Build') {
+      steps {
+        dir("${REPO}") {
+          xcoreAllAppsBuild('examples')
+          xcoreAllAppNotesBuild('examples')
+        }
+      }
+    }
+    stage('Test') {
+      steps {
+        runXmostest("${REPO}", "tests")
+      }
+    }
+  }
+  post {
+    always {
+      archiveArtifacts artifacts: "${REPO}/**/*.*", fingerprint: true
+      cleanWs()
+    }
+  }
+}

From 7b5e08d722872b16d043a3c68b1cda5c832cecec Mon Sep 17 00:00:00 2001
From: Sam Chesney <samc@xmos.com>
Date: Wed, 15 Aug 2018 11:37:25 +0100
Subject: [PATCH 09/10] Rename dieharder -> app_dieharder

Ensure CI system treats it as an xCORE application, and attempts a
build.
---
 examples/{dieharder => app_dieharder}/Makefile   | 0
 examples/{dieharder => app_dieharder}/README     | 0
 examples/{dieharder => app_dieharder}/src/gen.xc | 0
 3 files changed, 0 insertions(+), 0 deletions(-)
 rename examples/{dieharder => app_dieharder}/Makefile (100%)
 rename examples/{dieharder => app_dieharder}/README (100%)
 rename examples/{dieharder => app_dieharder}/src/gen.xc (100%)

diff --git a/examples/dieharder/Makefile b/examples/app_dieharder/Makefile
similarity index 100%
rename from examples/dieharder/Makefile
rename to examples/app_dieharder/Makefile
diff --git a/examples/dieharder/README b/examples/app_dieharder/README
similarity index 100%
rename from examples/dieharder/README
rename to examples/app_dieharder/README
diff --git a/examples/dieharder/src/gen.xc b/examples/app_dieharder/src/gen.xc
similarity index 100%
rename from examples/dieharder/src/gen.xc
rename to examples/app_dieharder/src/gen.xc

From 7fedf481d868266b3ec073e15429fce42e4e279d Mon Sep 17 00:00:00 2001
From: robert lytton <robert@xmos.com>
Date: Wed, 15 Aug 2018 12:31:06 +0100
Subject: [PATCH 10/10] Remove examples/AN002xx_... and random.h api

fix magic numbers
---
 .../AN002xx_random_number_generation/Makefile |   9 --
 .../README.rst                                |  34 ----
 .../SMART-MIC-4-TILE-1V0.xn                   | 153 ------------------
 .../config.xscope                             |  23 ---
 .../doc/rst/AN002xx.rst                       |  11 --
 .../doc/rst/xdoc.conf                         |   2 -
 .../src/random_numbers.xc                     | 136 ----------------
 lib_random/api/random.h                       |  55 -------
 lib_random/doc/rst/random.rst                 |  15 +-
 lib_random/module_build_info                  |   5 -
 lib_random/src/random.xc                      |  24 ---
 lib_random/src/random_bit.xc                  |  16 +-
 lib_random/src/random_deprecated.c            |  21 ---
 test/random/Makefile                          |  14 --
 test/random/expected.output                   |   4 -
 test/random/src/test.xc                       | 130 ---------------
 test/random_bit/Makefile                      |   8 -
 test/runtests.py                              |   2 +-
 test/test_random.py                           |  15 --
 19 files changed, 21 insertions(+), 656 deletions(-)
 delete mode 100644 examples/AN002xx_random_number_generation/Makefile
 delete mode 100644 examples/AN002xx_random_number_generation/README.rst
 delete mode 100755 examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn
 delete mode 100644 examples/AN002xx_random_number_generation/config.xscope
 delete mode 100644 examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst
 delete mode 100644 examples/AN002xx_random_number_generation/doc/rst/xdoc.conf
 delete mode 100644 examples/AN002xx_random_number_generation/src/random_numbers.xc
 delete mode 100755 lib_random/api/random.h
 delete mode 100755 lib_random/src/random.xc
 delete mode 100755 lib_random/src/random_deprecated.c
 delete mode 100644 test/random/Makefile
 delete mode 100644 test/random/expected.output
 delete mode 100755 test/random/src/test.xc
 delete mode 100755 test/test_random.py

diff --git a/examples/AN002xx_random_number_generation/Makefile b/examples/AN002xx_random_number_generation/Makefile
deleted file mode 100644
index b0101e3..0000000
--- a/examples/AN002xx_random_number_generation/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-TARGET = SMART-MIC-4-TILE-1V0
-APP_NAME =
-USED_MODULES = lib_random
-
-XCC_FLAGS = -O2 -g -Wunused -fxscope
-VERBOSE = 0
-
-XMOS_MAKE_PATH ?= ../..
--include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/examples/AN002xx_random_number_generation/README.rst b/examples/AN002xx_random_number_generation/README.rst
deleted file mode 100644
index a92471e..0000000
--- a/examples/AN002xx_random_number_generation/README.rst
+++ /dev/null
@@ -1,34 +0,0 @@
-Noise Suppression and Automatic Gain Control example
-====================================================
-
-.. version:: 0.0.1
-
-Summary
--------
-
-This example demonstrates how to use the automatic gain control library,
-the noise suppression library, and the microphone array library in order to
-create a meaningful AGC
-
-Required tools and libraries
-............................
-
-.. appdeps::
-
-Required hardware
-.................
-
-A smart microphone board.
-
-Prerequisites
-.............
-
- * This document assumes familiarity with the XMOS xCORE architecture,
-   the XMOS tool chain and the xC language. Documentation related to these
-   aspects which are not specific to this application note are linked to in
-   the references appendix.
-  
- * For a description of XMOS related terms found in this document
-   please see the XMOS Glossary [#]_.
-
-.. [#] http://www.xmos.com/published/glossary
diff --git a/examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn b/examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn
deleted file mode 100755
index 1bb07e9..0000000
--- a/examples/AN002xx_random_number_generation/SMART-MIC-4-TILE-1V0.xn
+++ /dev/null
@@ -1,153 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Network xmlns="http://www.xmos.com"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
-  <Type>Device</Type>
-  <Name>Mic Array Quad Tile</Name>
-
-  <Declarations>
-    <Declaration>tileref tile[4]</Declaration>
-    <Declaration>tileref usb_tile</Declaration>
-  </Declarations>
-
-  <Packages>
-    <Package id="0" Type="XS2-UFnA-512-TQ128">
-      <Nodes>
-          <Node Id="0" InPackageId="0" Type="XS2-L16A-512" Oscillator="24MHz" SystemFrequency="500MHz" ReferenceFrequency="100MHz">
-
-          <Boot>
-            <Source Location="bootFlash0"/>
-            <Bootee NodeId="2"/>
-          </Boot>
-          <Tile Number="0" Reference="tile[0]">
-            <!-- Quad flash ports -->
-            <Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
-            <Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
-            <Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
-
-            <Port Location="XS1_PORT_1M" Name="PORT_PLL_MOD"/>
-            <Port Location="XS1_PORT_1P" Name="PORT_BGT_SPI_CLK"/>
-            <Port Location="XS1_PORT_1A" Name="PORT_BGT_SPI_CS_N"/>
-            <Port Location="XS1_PORT_1F" Name="PORT_BGT_SPI_MISO"/>
-            <Port Location="XS1_PORT_1E" Name="PORT_BGT_SPI_MOSI"/>
-            <Port Location="XS1_PORT_1D" Name="PORT_BGT_IRQ"/>
-            <Port Location="XS1_PORT_1O" Name="PORT_I2C_SCL"/>
-            <Port Location="XS1_PORT_1N" Name="PORT_I2C_SDA"/>
-          </Tile>
-          <Tile Number="1" Reference="tile[1]">
-            <!-- USB -->
-            <Port Location="XS1_PORT_1H"  Name="PORT_USB_TX_READYIN"/>
-            <Port Location="XS1_PORT_1J"  Name="PORT_USB_CLK"/>
-            <Port Location="XS1_PORT_1K"  Name="PORT_USB_TX_READYOUT"/>
-            <Port Location="XS1_PORT_1I"  Name="PORT_USB_RX_READY"/>
-            <Port Location="XS1_PORT_1E"  Name="PORT_USB_FLAG0"/>
-            <Port Location="XS1_PORT_1F"  Name="PORT_USB_FLAG1"/>
-            <Port Location="XS1_PORT_1G"  Name="PORT_USB_FLAG2"/>
-            <Port Location="XS1_PORT_8A"  Name="PORT_USB_TXD"/>
-            <Port Location="XS1_PORT_8B"  Name="PORT_USB_RXD"/>
-
-            <!-- I2C -->
-            <!-- Note: Bit 1 of PORT 4E is I2C_SCL -->
-            <!--       Bit 2 of PORT 4E is I2C_SDA -->
-            <Port Location="XS1_PORT_4E" Name="PORT_I2C_SCL_SDA"/>
-            <Port Location="XS1_PORT_4F" Name="PORT_DAC_RST_N"/>
-
-            <!-- I2S -->
-            <Port Location="XS1_PORT_1M" Name="PORT_I2S_BCLK"/>
-            <Port Location="XS1_PORT_1N" Name="PORT_I2S_LRCLK"/>
-            <Port Location="XS1_PORT_1O" Name="PORT_MCLK_IN"/>
-            <Port Location="XS1_PORT_1P" Name="PORT_I2S_DAC0"/>
-            <Port Location="XS1_PORT_1L" Name="PORT_I2S_DAC1"/>
-            <Port Location="XS1_PORT_1C"  Name="PORT_I2S_ADC0"/>
-            <Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
-          </Tile>
-        </Node>
-        <Node Id="1" InPackageId="1" Type="periph:XS1-SU" Reference="usb_tile" Oscillator="24MHz"/>
-      </Nodes>
-      <Links>
-        <Link Encoding="5wire">
-          <LinkEndpoint NodeId="0" Link="8" Delays="52clk,52clk"/>
-          <LinkEndpoint NodeId="1" Link="XL0" Delays="1clk,1clk"/>
-        </Link>
-      </Links>
-    </Package>
-
-    <Package id="1" Type="XS2-LnA-512-TQ128">
-      <Nodes>
-        <Node Id="2" InPackageId="0" Type="XS2-L16A-512" SystemFrequency="500MHz" Oscillator="24MHz" ReferenceFrequency="100MHz">
-          <Boot>
-            <Source Location="LINK" BootMode="4"/>
-          </Boot>
-          <Tile Number="0" Reference="tile[2]">
-            <!-- Mics -->
-            <!-- Notes: XS1_PORT_4C is for mics 0, 1, 6 and 7 -->
-            <!--        XS1_PORT_4D is for mics 2, 3, 4 and 5 -->
-            <Port Location="XS1_PORT_8B" Name="PORT_PDM_DATA"/>
-            <Port Location="XS1_PORT_1G" Name="PORT_PDM_MCLK"/>
-            <Port Location="XS1_PORT_1H" Name="PORT_PDM_CLK"/>
-          </Tile>
-          <Tile Number="1" Reference="tile[3]">
-            <!-- Wireless LAN -->
-            <Port Location="XS1_PORT_1A" Name="PORT_WLAN_SPI_MOSI"/>
-            <Port Location="XS1_PORT_1B" Name="PORT_WLAN_SPI_MISO"/>
-            <Port Location="XS1_PORT_4A" Name="PORT_WLAN_WLAN_SPI_IRQ_N"/>
-            <!-- Note: Bit 1 of PORT 4B is WLAN_3V3_EN -->
-            <!--       Bit 2 of PORT 4B is WLAN_RST_N  -->
-            <Port Location="XS1_PORT_4B" Name="PORT_WLAN_3V3_EN_RST_N"/>
-            <Port Location="XS1_PORT_1C" Name="PORT_WLAN_SPI_CLK"/>
-            <Port Location="XS1_PORT_1D" Name="PORT_WLAN_SPI_CS_N"/>
-
-            <!-- Button ports -->
-            <Port Location="XS1_PORT_4C" Name="PORT_BUT_A_TO_D"/>
-
-            <!-- LED ports -->
-            <Port Location="XS1_PORT_8C" Name="PORT_LED0_TO_7"/>
-            <!-- Note: Only bits 4-7 of PORT 8D are for LEDs -->
-            <Port Location="XS1_PORT_8D" Name="PORT_LED8_TO_11"/>
-            <Port Location="XS1_PORT_1J" Name="PORT_LED_12"/>
-          </Tile>
-        </Node>
-      </Nodes>
-    </Package>
-  </Packages>
-
-  <Links>
-    <Link Encoding="2wire" Delays="3clk">
-      <LinkEndpoint NodeId="0" Link="7"/>
-      <LinkEndpoint NodeId="2" Link="0"/>
-    </Link>
-    <Link Encoding="5wire" Delays="3clk">
-      <LinkEndpoint NodeId="0" Link="4"/>
-      <LinkEndpoint NodeId="2" Link="3"/>
-    </Link>
-  </Links>
-
-  <!-- XSCOPE -->
-  <Nodes>
-    <Node Id="3" Type="device:" RoutingId="0x8000">
-      <Service Id="0" Proto="xscope_host_data(chanend c);">
-        <Chanend Identifier="c" end="3"/>
-      </Service>
-    </Node>
-  </Nodes>
-  <Links>
-    <Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
-      <LinkEndpoint NodeId="0" Link="XL0"/>
-      <LinkEndpoint NodeId="3" Chanend="1"/>
-    </Link>
-  </Links>
-
-  <ExternalDevices>
-    <Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash0">
-      <Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
-      <Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
-      <Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
-    </Device>
-  </ExternalDevices>
-
-  <JTAGChain>
-    <JTAGDevice NodeId="0"/>
-    <JTAGDevice NodeId="2"/>
-  </JTAGChain>
-
-</Network>
diff --git a/examples/AN002xx_random_number_generation/config.xscope b/examples/AN002xx_random_number_generation/config.xscope
deleted file mode 100644
index 6436587..0000000
--- a/examples/AN002xx_random_number_generation/config.xscope
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<!-- ======================================================= -->
-<!-- The 'ioMode' attribute on the xSCOPEconfig              -->
-<!-- element can take the following values:                  -->
-<!--   "none", "basic", "timed"                              -->
-<!--                                                         -->
-<!-- The 'type' attribute on Probe                           -->
-<!-- elements can take the following values:                 -->
-<!--   "STARTSTOP", "CONTINUOUS", "DISCRETE", "STATEMACHINE" -->
-<!--                                                         -->
-<!-- The 'datatype' attribute on Probe                       -->
-<!-- elements can take the following values:                 -->
-<!--   "NONE", "UINT", "INT", "FLOAT"                        -->
-<!-- ======================================================= -->
-
-<xSCOPEconfig ioMode="basic" enabled="false">
-
-    <!-- For example: -->
-    <Probe name="CH0" type="CONTINUOUS" datatype="INT" units="Value" enabled="true"/>
-    <!-- From the target code, call: xscope_int(PROBE_NAME, value); -->
-
-</xSCOPEconfig>
diff --git a/examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst b/examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst
deleted file mode 100644
index 08592a2..0000000
--- a/examples/AN002xx_random_number_generation/doc/rst/AN002xx.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-.. include:: ../../README.rst
-
-|newpage|
-
-Overview
---------
-
-Introduction
-............
-
-This demo application shows how to use random numbers.
diff --git a/examples/AN002xx_random_number_generation/doc/rst/xdoc.conf b/examples/AN002xx_random_number_generation/doc/rst/xdoc.conf
deleted file mode 100644
index cb5aab6..0000000
--- a/examples/AN002xx_random_number_generation/doc/rst/xdoc.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-XMOSNEWSTYLE=1
-SOURCE_INCLUDE_DIRS=../../src
diff --git a/examples/AN002xx_random_number_generation/src/random_numbers.xc b/examples/AN002xx_random_number_generation/src/random_numbers.xc
deleted file mode 100644
index 3c94404..0000000
--- a/examples/AN002xx_random_number_generation/src/random_numbers.xc
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <xs1.h>
-#include "random_bit.h"
-
-#define MAXX 1024
-#define MAXY 1024
-#define MAXBITS (MAXX * MAXY)
-
-unsigned char thebits[MAXBITS/8];
-
-unsigned int getbit(int i) {
-  return (thebits[i>>3] >> (i&7)) & 1;
-}
-
-unsigned int setbit(int i, int val) {
-  return thebits[i>>3] |= val << (i&7);
-}
-
-void blocktest(int n) {
-  int hist[256];
-  for(int i = 0; i < 256; i++) {
-    hist[i] = 0;
-  }
-  for(int i = 0; i < MAXBITS - n; i++) {
-    int val = 0;
-    for(int j = 0; j < n; j++) {
-      val = val << 1 | getbit(i+j);
-    }
-    hist[val]++;
-  }
-  printf("Blocktest %d\n", n);
-  for(int i = 0; i < (1<<n); i++) {
-    printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i]-(MAXBITS >> n)) < MAXX ? "Ok" : "Hmm");
-  }
-  printf("\n");
-}
-
-void runtest() {
-  int hist[200];
-  int old = 0;
-  int run = 0;
-  for(int i = 0; i < 200; i++) {
-    hist[i] = 0;
-  }
-  for(int i = 0; i < MAXBITS; i++) {
-    if(getbit(i) == old) {
-      run++;
-    } else {
-      hist[run]++;
-      run = 1;
-    }
-  }
-  printf("Runtest:\n");
-  for(int i = 1; i < 10; i++) {
-    printf("  Bin %d: %d %s\n", i, hist[i], abs(hist[i] - (MAXBITS >> (i+1))) < (MAXX >> (i/2)) ? "Ok" : "Hmm" );
-  }
-  printf("\n");
-}
-
-void fillmetrue(void) {
-  timer tmr;
-  int t0, t1;
-  int sum = 0;
-  tmr :> t0;
-  random_bit_start();
-  while(sum < MAXBITS) {
-    uint32_t bit_time;
-    if (random_bit(bit_time)) {
-      //assert((bit_time & ~1UL)==0);
-      setbit(sum, bit_time);
-      sum++;
-      if ((sum & 0xffff) == 0) {
-        int time;
-        asm volatile ("gettime %0" : "=r" (time));
-        printf("%11d %d\n", time, sum);
-      }
-    }
-    //else
-    //  tmr when timerafter(bit_time) :> void;
-  }
-  random_bit_stop();
-  tmr :> t1;
-  printf("Ticks taken: %d, %d per bit\n", t1-t0, (t1-t0)/sum);
-}
-
-void xmain(chanend done[7]) {
-  for(int i = 0; i < 7; i++) {
-    done[i] <: 0;
-  }
-  fillmetrue();
-  blocktest(1);
-  blocktest(2);
-  blocktest(3);
-  runtest();
-  return;
-  printf("P2\n%d %d\n1\n", MAXX, MAXY);
-  for(int i = 0; i < MAXX; i++) {
-    for(int j = 0; j < MAXY; j++) {
-      printf("%d ", getbit(i*MAXY+j));
-    }
-    printf("\n");
-  }
-}
-
-int busy(int x, chanend y) {
-  while(1) {
-    for(int i = 0; i < 1000; i++) {
-      x = x * 1234567 + 1;
-    }
-    select {
-      case y :> int _: return x;
-      default:  break;
-    }
-  }
-  return x;
-}
-
-
-int main(void) {
-  chan done[7];
-  par {
-    busy(0x3, done[0]);
-    busy(0x4, done[1]);
-    busy(0x5, done[2]);
-    busy(0x6, done[3]);
-    busy(0x7, done[4]);
-    busy(0x8, done[5]);
-    busy(0x9, done[6]);
-    xmain(done);
-  }
-  return 0;
-}
diff --git a/lib_random/api/random.h b/lib_random/api/random.h
deleted file mode 100755
index fec5350..0000000
--- a/lib_random/api/random.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
-#ifndef __RANDOM_H__
-#define __RANDOM_H__
-
-#include <stdint.h>
-#include <stddef.h>
-
-#ifndef REFERENCE_PARAM
-#ifdef __XC__
-#define REFERENCE_PARAM(type, name) type &name
-#else
-#define REFERENCE_PARAM(type, name) type *name
-#endif
-#endif
-
-/** This is an alternative pseudo-random number generator to those offered by stdlib.h:
- *  rand, srand, rand_r, drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, seed48, srand48
- *  It uses the built in crc32() instructions.
- */
-
-/** Type representing a random number generator.
- */
-typedef unsigned random_generator_t;
-
-/** Function that creates a random number generator from a seed.
- *
- * \param seed  seed for the generator.
- *
- * \returns     a random number generator.
- */
-random_generator_t random_create_generator_from_seed(unsigned seed);
-
-
-/** Function that produces a random number. The number has a cycle of 2^32
- *  and is produced using a LFSR.
- *
- *  \param g    the used generator to produce the seed.
- *
- *  \returns    a random 32 bit number.
- */
-unsigned
-random_get_random_number(REFERENCE_PARAM(random_generator_t, g));
-
-void random_get_random_bytes(REFERENCE_PARAM(random_generator_t, g), uint8_t in_buffer[], size_t byte_count);
-
-
-// The following function is deprecated.
-// It is incompatible with the rest of the lib_random library.
-// To use this function you must define in your Makefile:
-//    RANDOM_ENABLE_HW_SEED=1
-//__attribute__((deprecated)) // Use random_prng.h instead.
-random_generator_t random_create_generator_from_hw_seed(void);
-
-
-#endif // __RANDOM_H__
diff --git a/lib_random/doc/rst/random.rst b/lib_random/doc/rst/random.rst
index 389f89a..ce74172 100644
--- a/lib_random/doc/rst/random.rst
+++ b/lib_random/doc/rst/random.rst
@@ -4,18 +4,19 @@ API
 ---
 
 To use the module you need to use ``lib_random`` in your application and
-include the ``random.h`` header.
-
-
-
+include only one of the ``api`` header files.
+The three APIs are nested, hence you should choose the one that gives you
+the required level of functionality.
+In most cases, you will want to be using the top level, ``random_prng.h``.
+The top level is built upon the lower level, hence access to entropy.
 
+For alternative PRNG see stdlib.h which includes:
+   rand, srand, rand_r, drand48, erand48, jrand48, lcong48, lrand48,
+   mrand48, nrand48, seed48, srand48.
 
 |appendix|
 
 Known Issues
 ------------
 
-The deprecated random_create_generator_from_hw_seed() functionality will not work corrrectly
-along side random_bit.h (and hence random_pool.h and random_prng.h)
-
 .. include:: ../../../CHANGELOG.rst
diff --git a/lib_random/module_build_info b/lib_random/module_build_info
index 0828bac..d2d3c17 100755
--- a/lib_random/module_build_info
+++ b/lib_random/module_build_info
@@ -1,10 +1,5 @@
 MODULE_XCC_FLAGS = -g -Os
 #MODULE_XCC_FLAGS += -save-temps -v
 
-# Enable deprecated features
-ifneq ($(RANDOM_ENABLE_HW_SEED),)
-MODULE_XCC_FLAGS += -DRANDOM_ENABLE_HW_SEED=$(RANDOM_ENABLE_HW_SEED)
-endif
-
 DEPENDENT_MODULES = lib_locks lib_xassert
 VERSION = 1.1.0
diff --git a/lib_random/src/random.xc b/lib_random/src/random.xc
deleted file mode 100755
index 9d32dfe..0000000
--- a/lib_random/src/random.xc
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
-#include "random.h"
-#include <xs1.h>
-
-unsigned random_get_random_number(random_generator_t &g)
-{
-  static const unsigned random_poly = 0xEDB88320;
-  crc32(g, -1, random_poly);
-  return (unsigned) g;
-}
-
-void random_get_random_bytes(random_generator_t &g, uint8_t in_buffer[], size_t byte_count)
-{
-  for (int i=0; i < byte_count; ++i) {
-    in_buffer[i] = (uint8_t)random_get_random_number(g);
-  }
-}
-
-random_generator_t random_create_generator_from_seed(unsigned seed)
-{
-  random_generator_t gen = (random_generator_t) seed;
-  (void) random_get_random_number(gen);
-  return gen;
-}
diff --git a/lib_random/src/random_bit.xc b/lib_random/src/random_bit.xc
index 3b48acc..cd7f748 100755
--- a/lib_random/src/random_bit.xc
+++ b/lib_random/src/random_bit.xc
@@ -3,6 +3,14 @@
 #include "hwlock.h"
 #include "random_impl.h"
 
+#if __XS2__
+#  include "xs2a_registers.h"
+#else
+#  include "xs1b_registers.h"
+#  define XS1_PS_RING_OSC_CTRL   XS1_L_PS_RING_OSC_CTRL
+#  define XS1_PS_RING_OSC_DATA0  XS1_L_PS_RING_OSC_DATA0
+#endif
+
 // Optional thread protection...
 
 #define LOAD32(dst, ptr)       asm("ldw %0, %1[0]"  : "=r"(dst) : "r"(ptr));
@@ -38,11 +46,11 @@ void random_bit_start() {
   timer tmr;
   tmr :> last_time;
   STORE32(last_time, &per_tile_last_time);
-  setps(0x60B, 2);
+  setps(XS1_PS_RING_OSC_CTRL, 2);
 }
 
 void random_bit_stop() {
-  setps(0x60B, 0);
+  setps(XS1_PS_RING_OSC_CTRL, 0);
 }
 
 uint32_t random_bit(uint32_t &bit_time) {
@@ -58,8 +66,8 @@ uint32_t random_bit(uint32_t &bit_time) {
     asm("nop");
     asm("nop");
     asm("nop");
-    asm("nop");
-    bit_time = getps(0x70B);
+    asm("nop"); // Allow the data to stabilise.
+    bit_time = getps(XS1_PS_RING_OSC_DATA0);
     random_bit_start();
     bit_time &=1;
     return 1;
diff --git a/lib_random/src/random_deprecated.c b/lib_random/src/random_deprecated.c
deleted file mode 100755
index 711102e..0000000
--- a/lib_random/src/random_deprecated.c
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2016-2017, XMOS Ltd, All rights reserved
-#include "random.h"
-#include <xs1.h>
-
-#if RANDOM_ENABLE_HW_SEED
-
-#warning "Building deprecated random_create_generator_from_hw_seed()"
-#warning "N.B. random_create_generator_from_hw_seed() is incompatible with the rest of the lib_random library."
-#warning "Did you mean to define `RANDOM_ENABLE_HW_SEED`?"
-
-__attribute__((constructor))
-void random_simple_init_seed() {
-  setps(0x060B, 0x3);
-}
-
-random_generator_t random_create_generator_from_hw_seed(void) {
-  unsigned init_seed = getps(0x070B);
-  return random_create_generator_from_seed(init_seed);
-}
-
-#endif
diff --git a/test/random/Makefile b/test/random/Makefile
deleted file mode 100644
index b0ceab1..0000000
--- a/test/random/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-TARGET = SLICEKIT-L16
-APP_NAME =
-USED_MODULES = lib_random
-
-XCC_FLAGS = -Os -g
-#XCC_FLAGS += -save-temps -v
-
-# We will be testing the deprecated interface...
-RANDOM_ENABLE_HW_SEED=1
-
-VERBOSE = 0
-
-XMOS_MAKE_PATH ?= ../..
--include $(XMOS_MAKE_PATH)/xcommon/module_xcommon/build/Makefile.common
diff --git a/test/random/expected.output b/test/random/expected.output
deleted file mode 100644
index e22e136..0000000
--- a/test/random/expected.output
+++ /dev/null
@@ -1,4 +0,0 @@
-test-3 done.
-test-2 done.
-test-0 done.
-test-1 done.
diff --git a/test/random/src/test.xc b/test/random/src/test.xc
deleted file mode 100755
index 6ba3ec1..0000000
--- a/test/random/src/test.xc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright (c) 2017, XMOS Ltd, All rights reserved
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <platform.h>
-#include "random.h"
-
-/////////////////////////////////////////////////////////
-// First some unit testing boiler plate
-interface checker {
-  void str(const char str[100]);
-  void release();
-};
-static void checkerServer(server interface checker si[n], static const size_t n, uint32_t timeout) {
-  // We will release when the last client has released us.
-  // All clients have implicitly claimed us, set the 'n' lowest bits.
-  if (n > 32) {
-    fprintf(stderr, "Error checkerServer: The maximum number of clients is 32\n");
-    return;
-  }
-  uint32_t activeClients = (1ULL<<n) - 1;
-
-  // Attempt to spot hung tests.
-  timer tmr;
-  uint32_t start;
-  tmr :> start;
-
-  while(1){
-    select{
-      case si[unsigned id].str(const char str[100]) :
-        char local[100];
-        memcpy(local,str,100);
-        fprintf(stderr, "%s\n", local);
-        break;
-      case si[unsigned id].release():
-        activeClients &= ~(1UL << id);
-        if (!activeClients)
-          return;
-        break;
-      case  tmr when timerafter(start + timeout) :> void:
-        fprintf(stderr, "Error checkerServer: timout after %d tick, activeClients mask=0x%X\n", timeout, activeClients);
-        exit(1);
-        break;
-    }
-  }
-}
-
-#define INFO(ci, ...) \
-  do { \
-    char _checker_buff[100]; \
-    snprintf(_checker_buff, 100, __VA_ARGS__); \
-    ci.str(_checker_buff); \
-  } while(0)
-
-#define CHECK(c, ci, ...) \
-  if (!(c)) INFO(ci, __VA_ARGS__)
-
-/////////////////////////////////////////////////////////
-
-typedef union {
-  uint32_t word[2];
-  uint8_t byte[8];
-} Bytes;
-
-
-void test(client interface checker ci, int id) {
-
-  // Check '0' is valid.
-  random_generator_t gen1 = random_create_generator_from_seed(0);
-  unsigned v1 = random_get_random_number(gen1);
-  CHECK( v1, ci, "test-%d unexpexted zero returned", id );
-  Bytes b1 = {{0,0}};
-  random_get_random_bytes(gen1, b1.byte, 5);
-  // simple checks of the values returned...
-  CHECK( b1.word[0] && b1.word[1], ci, "test-%d unexpexted zero returned, %#08X%08x", id, b1.word[0], b1.word[1] );
-  CHECK( (b1.word[1] & 0xffffff00) == 0, ci, "test-%d too many bytes read, %#08X%08x", id, b1.word[0], b1.word[1] );
-  // We do not test for 'out of bounds array access'
-  // random_get_random_bytes(gen1, b1.byte, 11);
-
-  // Check we get a different set of values.
-  random_generator_t gen2 = random_create_generator_from_seed(0x12345678);
-  unsigned v2 = random_get_random_number(gen2);
-  CHECK( v2 != v1, ci, "test-%d unexpexted same value", id );
-  Bytes b2 = {{0,0}};
-  random_get_random_bytes(gen2, b2.byte, 5);
-  CHECK( b2.word[0] != b1.word[0] && b2.word[1] != b1.word[1], ci, "unexpexted same bytes", id );
-
-  // We should get the same output as the first block.
-  random_generator_t gen3 = random_create_generator_from_seed(0);
-  unsigned v3 = random_get_random_number(gen3);
-  CHECK( v3 == v1, ci, "test-%d unexpexted different value", id );
-  Bytes b3 = {{0,0}};
-  random_get_random_bytes(gen3, b3.byte, 5);
-  CHECK( b3.word[0] == b1.word[0] && b3.word[1] == b1.word[1], ci, "unexpexted different bytes", id );
-
-  // All gernators are independant.
-  v1 = random_get_random_number(gen1);
-  v2 = random_get_random_number(gen2);
-  v3 = random_get_random_number(gen3);
-  CHECK( v2 != v1, ci, "test-%d unexpexted same value", id );
-  CHECK( v3 == v1, ci, "test-%d unexpexted different value", id );
-
-  Bytes zero = {{0,0}};
-  random_get_random_bytes(gen1, zero.byte, 0);
-  CHECK( !zero.word[0] && !zero.word[1], ci, "unexpexted bytes read", id );
-
-  // The following function is deprecated but still tested.
-  // We have add 'RANDOM_ENABLE_HW_SEED=1' to the Makefile.
-  // The build will generate a warning... which we ignore.
-  random_generator_t gen4 = random_create_generator_from_hw_seed();
-  // No delay needed.
-  random_generator_t gen5 = random_create_generator_from_hw_seed();
-  CHECK( gen4 != gen5, ci, "test-%d same hw seed generator", id );
-
-  INFO(ci, "test-%d done.", id);
-  ci.release();
-}
-
-int main() {
-  interface checker i[4];
-  par {
-    on tile[0] : checkerServer(i, 4, 100000);
-    on tile[0] : test(i[0], 0);
-    on tile[0] : test(i[1], 1);
-    on tile[1] : test(i[2], 2);
-    on tile[1] : test(i[3], 3);
-  }
-  return 0; // failure;
-}
diff --git a/test/random_bit/Makefile b/test/random_bit/Makefile
index ef987ff..85cb9fd 100755
--- a/test/random_bit/Makefile
+++ b/test/random_bit/Makefile
@@ -3,14 +3,6 @@ APP_NAME =
 USED_MODULES = lib_random
 
 XCC_FLAGS = -Os -g
-#XCC_FLAGS += -save-temps -v
-
-# RANDOM_ENABLE_HW_SEED must either:
-#    not be declared at all
-#    or if it is, take the value '0'.
-# We chose the second option here as an example, other tests do not declare it at all.
-# N.B. We expect random_deprecated.c not to be built.
-RANDOM_ENABLE_HW_SEED=0
 
 VERBOSE = 0
 
diff --git a/test/runtests.py b/test/runtests.py
index d422f09..07130d4 100755
--- a/test/runtests.py
+++ b/test/runtests.py
@@ -3,7 +3,7 @@
 
 if __name__ == "__main__":
     xmostest.init()
-    xmostest.register_group("lib_random", "lib_random_tests", "lib_random library tests", "Tests random_bit.h, random_pool.h, random_prng.h and random.h")
+    xmostest.register_group("lib_random", "lib_random_tests", "lib_random library tests", "Tests random_bit.h, random_pool.h and random_prng.h")
     xmostest.runtests()
     xmostest.finish()
 
diff --git a/test/test_random.py b/test/test_random.py
deleted file mode 100755
index 845222b..0000000
--- a/test/test_random.py
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/usr/bin/env python
-import xmostest
-
-def runtest():
-    resources = xmostest.request_resource("xsim")
-
-    tester = xmostest.ComparisonTester(open('random/expected.output'),
-                                       'lib_random',
-                                       'lib_random_tests',
-                                       'random', {})
-
-    xmostest.run_on_simulator(resources['xsim'],
-                              'random/bin/random.xe',
-                              tester=tester)
-