diff --git a/BOM/README.md b/BOM/README.md
index c0ed905..8af42b5 100644
--- a/BOM/README.md
+++ b/BOM/README.md
@@ -1,7 +1,7 @@
-# Bill of materials for V0 Electronics and Enclosure
+# Bill of materials for Electronics and Enclosure
## V0
-!Bill of materials [link](https://docs.google.com/a/berkeley.edu/spreadsheets/d/1bNN8tflB9aEgVB0fuUHVAcNsngxJomVvjAU4SV36tMI/edit?usp=sharing).
+Bill of materials [spreadsheet](https://docs.google.com/a/berkeley.edu/spreadsheets/d/1bNN8tflB9aEgVB0fuUHVAcNsngxJomVvjAU4SV36tMI/edit?usp=sharing).
## V1
coming soon
diff --git a/README.md b/README.md
index 4aa648a..15572c7 100644
--- a/README.md
+++ b/README.md
@@ -1,20 +1,24 @@
# MyPart
-design files for low cost particle counter
+Design files for low cost laser air particle counter
-## intro
+## Intro
![quarter for scale](/media/with_quarter.jpg)
-## performance data
+## Mechanism
+![exploded drawing](/media/exploded.png)
+
+## Preliminary performance data
+Measured against the MetOne HHPC-6 (~$4000 USD) across 20 locations.
![small particles](/media/corr_small.png)
![large particles](/media/corr_large.png)
-
## Form factor exploration
-
![form factors](/media/form_factors.png)
+
+
diff --git a/electrical/README.md b/electrical/README.md
new file mode 100644
index 0000000..834f473
--- /dev/null
+++ b/electrical/README.md
@@ -0,0 +1,7 @@
+# Eagle files for the circuit boards
+
+small_top_everything is the main PCB
+
+programming_header connects the standard RFDuino programmer to the main PCB through pogo pins.
+
+
diff --git a/electrical/small_top_everything_revB.brd b/electrical/small_top_everything.brd
similarity index 63%
rename from electrical/small_top_everything_revB.brd
rename to electrical/small_top_everything.brd
index 1ab8e60..b3298bb 100644
--- a/electrical/small_top_everything_revB.brd
+++ b/electrical/small_top_everything.brd
@@ -6,7 +6,7 @@
-
+
@@ -146,7 +146,7 @@
-REV_B
+REV_A
@@ -168,12 +168,22 @@
for_monitoring
1st stage
Connect: TP3 & TP0
+
+
+
+
+
+
+
+
+LPKF optimized
+REV_A
MyPart
-
+
-
+
@@ -204,10 +214,6 @@ Connect: TP3 & TP0
-
-
-
-
@@ -387,31 +393,6 @@ Connect: TP3 & TP0
>VALUE
-
-<b>RGB LED PLCC4</b>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -441,6 +422,42 @@ Connect: TP3 & TP0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
<b>Small Outline Transistor</b> 6 lead
@@ -492,6 +509,56 @@ Connect: TP3 & TP0
>Name
>Value
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+>NAME
+>VALUE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+>Name
+>Value
+
@@ -506,102 +573,26 @@ Connect: TP3 & TP0
>VALUE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
->NAME
->VALUE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
->NAME
->VALUE
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+>NAME
+>VALUE
+
+
+
+
+
+
+
+
+
+
+
+
@@ -672,6 +663,30 @@ package type OT
+
+<b>CHIPLED</b><p>
+Source: http://www.osram.convergy.de/ ... LG_LY Q971.pdf
+
+
+
+
+
+
+
+>NAME
+>VALUE
+
+
+
+
+
+
+
+
+
+
+
+
@@ -910,8 +925,8 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
-
+
+
@@ -951,26 +966,27 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
@@ -978,32 +994,40 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
-
+
-
+
-
-
-
-
-
-
-
-
-
@@ -1023,15 +1047,16 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
+
+
-
-
-
+
@@ -1065,51 +1090,58 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
+
+
+
-
-
-
+
+
+
-
-
+
+
-
-
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
@@ -1121,11 +1153,11 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
+
+
+
-
-
-
-
@@ -1144,17 +1176,20 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
-
-
-
+
+
+
+
+
-
+
@@ -1165,7 +1200,7 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
+
@@ -1188,7 +1223,7 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
+
@@ -1204,6 +1239,15 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
+
+
+
+
+
+
+
+
@@ -1215,14 +1259,17 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
-
-
+
+
+
+
+
+
@@ -1231,92 +1278,101 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
@@ -1325,18 +1381,21 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
-
+
+
+
+
+
-
+
@@ -1345,144 +1404,214 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
+
@@ -1500,72 +1629,225 @@ This DRC checks for the absolute minimum clearances and should only be used when
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
-
-
+
+
@@ -1590,62 +1872,63 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
+
-
-
-
-
+
+
+
-
-
-
-
+
+
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
@@ -1660,78 +1943,18 @@ This DRC checks for the absolute minimum clearances and should only be used when
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/mechanical/button.stl b/mechanical/button.stl
new file mode 100644
index 0000000..e3462fd
Binary files /dev/null and b/mechanical/button.stl differ
diff --git a/mechanical/laser_holder.stl b/mechanical/laser_holder.stl
new file mode 100644
index 0000000..487f99b
Binary files /dev/null and b/mechanical/laser_holder.stl differ
diff --git a/mechanical/middle.stl b/mechanical/middle.stl
new file mode 100644
index 0000000..63b5d22
Binary files /dev/null and b/mechanical/middle.stl differ
diff --git a/mechanical/top.stl b/mechanical/top.stl
new file mode 100644
index 0000000..5f6a73f
Binary files /dev/null and b/mechanical/top.stl differ
diff --git a/production_files/README.md b/production_files/README.md
index 8b183c9..03b4a71 100644
--- a/production_files/README.md
+++ b/production_files/README.md
@@ -1,2 +1,4 @@
-# All production files in one place (gerbers/stls)
+# All production files in one place (gerbers/stls/firmware)
+
+
diff --git a/production_files/software/V0/V0.ino b/production_files/software/V0/V0.ino
new file mode 100644
index 0000000..1a5fe20
--- /dev/null
+++ b/production_files/software/V0/V0.ino
@@ -0,0 +1,324 @@
+/*****************************************************************
+*
+* Simple code to interface air particle counter with outside world
+*
+* normally in ULP sleep
+*
+* when awoken, (1) shine lights while fan warms up, (2) dim lights,
+* (3) sample for 5 seconds, (4) shine leds according to numPeaks,
+* (5) broadcast that data for 10 seconds over bluetooth
+*
+* Rundong Tian
+* 9/13/2015
+*
+*****************************************************************/
+
+#include
+#include // need to modify board def to change which are SPI pins
+#include
+#include "TLC59108.h" // 8 channel LED driver
+#include "Adafruit_HDC1000.h" // humidity/temperature sensor
+#include "PCA9536.h" // gpio expander
+
+#include
+#include
+
+Adafruit_HDC1000 hdc = Adafruit_HDC1000(); // init humidty/temp object
+PCA9536 gpio;
+
+//for the 8 leds
+#define I2C_ADDR TLC59108::I2C_ADDR::SUB4
+TLC59108 leds(I2C_ADDR);
+const int numled = 8;
+
+
+const int CS = 3; // SPI cs for ADC
+const int wake = 6; // waking up from ULP
+
+// for gpio
+const int laser = 1;
+const int fan = 2;
+const int ledRST = 0;
+
+// variables for particle counting
+const int small_thresh = 370; // ~.3 Volts
+const int large_thresh = 1500; // ~1.5 Volts
+const int hyst = 10; // maybe for later
+
+// keep track of counts
+int small_count = 0;
+int large_count = 0;
+
+
+// for BLE
+const int interval = 675; // interval (ms) for BLE broadcast 500 - 1000 is sweet spot
+
+/****************************************
+* function to run upon wakeup
+* this function does most of the work.
+* blinks the lights, counts the particles,
+* measures humidity/temperature, yelss out over BLE
+*
+****************************************/
+int onWake(uint32_t ulPin) { // you've been frenched!!!
+
+ RFduino_resetPinWake(wake);
+
+ // turn on the fan and laser
+ gpio.writePin(fan,1);
+ gpio.writePin(laser,1);
+
+ // briefly make some lights as the fan is spinning up
+ leds.init();
+ leds.setLedOutputMode(TLC59108::LED_MODE::PWM_IND);
+
+ uint8_t gap = 130;
+ int zero = 0;
+ leds.setAllBrightness(0xff);
+ delay(gap);
+ leds.setAllBrightness(zero);
+ delay(gap);
+ leds.setAllBrightness(0xff);
+ delay(gap);
+
+ for(int pwm = 0x0ff; pwm >= 0x00; pwm--) {
+ leds.setAllBrightness(pwm);
+ delay(1);
+ }
+
+ fade2zero(8);
+
+ // read the humidity
+ int b = hdc.begin();
+ float temp = hdc.readTemperature();
+ float hum = hdc.readHumidity();
+
+ // reset the number of counts
+
+ small_count = 0;
+ large_count = 0;
+ int total_count = 0;
+ int total_count_prev = 0; // helps us keep track of current led state
+
+
+ // count for 15 seconds
+ for (int i = 0; i < 15; i++) {
+ int data = count_one_second();
+ int data_copy = data;
+
+ small_count += ((data_copy << 16) >> 16);
+ large_count += (data >> 16);
+
+ //shine some lights
+ total_count = small_count; // small count is secretly all counts
+ counts2lights(total_count_prev, total_count); // from, to, wait
+ total_count_prev = total_count;// update prev
+ }
+
+ // turn off all gpios.
+ gpio.writePin(fan,0);
+ gpio.writePin(laser,0);
+
+ char small_str[6] ;
+ char large_str[6] ;
+
+
+
+ sprintf(small_str,"%d",min(small_count - large_count, 999999));
+ sprintf(large_str,"%d",min(large_count, 999999));
+
+ strcat(small_str, ",");
+ strcat(small_str, large_str);
+ // put the two together
+
+ // ble broadcast
+ RFduinoBLE.advertisementData = small_str;
+
+ // start the BLE stack
+ RFduinoBLE.begin();
+ // advertise for ms milliseconds
+ RFduino_ULPDelay(10000);
+ // stop the BLE stack
+ RFduinoBLE.end();
+
+ fade2zero(1);
+ return(0); // go back to sleep
+
+}
+
+
+
+/****************************
+* helper function for mapping the number of particles
+* to light levels
+*****************************/
+void counts2lights(int from, int to) {
+
+ int scale = 10; // scaling the input values to get full range on the lights
+
+ // we have 2047 discrete levels we can represent
+ from = min(from * scale, 2047);
+ to = min(to * scale, 2047);
+
+ for (int i = from; i < to ; i+=32) {
+ uint8_t channel = i/256;
+ uint8_t channel_brightness = i%256;
+ leds.setBrightness(channel, channel_brightness);
+ }
+
+}
+
+/****************************
+* helper function for fadding all of the lights
+* after they commmunicate the number of particles in the air
+*****************************/
+void fade2zero(int wait) {
+
+ // read current light level
+ uint8_t dutyCycles[8];
+ leds.getAllBrightness(dutyCycles);
+
+ // fade from the top
+ for (int i = 7 ; i >= 0 ; i-- ) { // fade from top led
+ for (int j = dutyCycles[i]; j>=0; j--) { // fade each led to zero from it's current value
+ leds.setBrightness(i, j);
+ delay(wait);
+ }
+ }
+
+}
+
+void setup() {
+
+ pinMode(CS, OUTPUT); // must manually toggle CS for nrf51*
+
+ Wire.beginOnPins(1,0);
+ gpio = PCA9536();
+ gpio.configurePins(1, 0, 0, 0); // configure gpio as all output
+ // turn everything off
+ gpio.writePin(3, 0);
+ gpio.writePin(fan, 0);
+ gpio.writePin(laser, 0);
+
+
+ /* setup the wakeup pin */
+ pinMode(wake, INPUT_PULLUP); // configure wakeup pin as input
+ RFduino_pinWakeCallback(wake, LOW, onWake);
+
+ /* set up a few ble parameters */
+ RFduinoBLE.deviceName = "myPart";
+ RFduinoBLE.advertisementInterval = 500; // 500 ms
+ RFduinoBLE.txPowerLevel = 4; //-20 to +4 in 4 dB increments
+
+ RFduino_ULPDelay(INFINITE); // go to sleep forever, until you've been frenched by a handsome prince
+
+}
+
+/*******************
+* Samples for 1 second, reports back big and small counts
+* returns int: large counts as top 16 bits, small counts as lower 16 bits
+* current sample rate:
+********************/
+
+int count_one_second(void)
+{
+
+ unsigned int i = 0;
+ unsigned int lc = 0; // large counts
+ unsigned int sc = 0; // small counts
+ unsigned int particle_check[] = {65535, 65535}; // tiny buffer to check if particles are big enough
+
+ SPI.begin();
+
+ // for now, determine the cutoff count emperically
+ while (i < 87720) { // number of samples determined emperically. Sampling as fast as processing 'algorithm' will allow
+
+ NRF_GPIO->OUTCLR = (1 << CS); // chip select
+
+ //begin spi stuff
+ NRF_SPI0->TXD = 0x0;
+ NRF_SPI0->TXD = 0x0; // double buffer
+
+ /******* first byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ byte data1 = NRF_SPI0->RXD;
+
+ /******* second byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ byte data2 = NRF_SPI0->RXD;
+
+ /******* release CS ***********/
+ NRF_GPIO->OUTSET = (1 << CS); // digitalWrite(CS, HIGH);
+
+ /************ math begin **************************/
+ int data = data2 | (data1 << 8); // concatenate the two things
+ byte curr = i&1;
+ byte prev = (i-1)&1; // TODO: check for corner case at beginning or end of int
+
+ particle_check[curr] = data; // write data into our "circular buffer"
+
+ // check for sizing
+ if ( particle_check[curr] > small_thresh && particle_check[prev] < small_thresh) {
+ sc++;
+ }
+ if ( particle_check[curr] > large_thresh && particle_check[prev] < large_thresh) {
+ lc++;
+ }
+
+ i++;
+
+ } // end while
+
+ SPI.end();
+ return (lc << 16) | sc; // large counts (lc) as top 16 bits, sc as lower 16 bits
+
+
+}
+
+
+/********************************************
+* Timer configuration for 20us sampling period
+*********************************************/
+void timer_1_config(void)
+{
+ NRF_TIMER1->TASKS_STOP = 1; // Stop timer
+ NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; // fancy name for 0 (timer mode
+ NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);
+ NRF_TIMER1->PRESCALER = 4; // SysClk/2^PRESCALER) = 16,000,000/16 = 1us resolution
+ NRF_TIMER1->TASKS_CLEAR = 1; // Clear TIMER
+ NRF_TIMER1->CC[0] = 20; // 20 us capture/compare register
+ NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; // set interrupt enable in the compare[0] position
+ NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
+
+ NRF_TIMER1->TASKS_START = 1; // Start TIMER
+}
+
+/***************************
+* Timer interrupt, potentially used for sampling at a more consistent rate
+*
+****************************/
+void TIMER1_IRQHandler(void)
+{
+
+ if (NRF_TIMER1->EVENTS_COMPARE[0] != 0) // for the 20us timer
+ {
+
+ NRF_TIMER1->EVENTS_COMPARE[0] = 0; // clear the register
+ }
+}
+
+void loop() { // nothing in loop
+// int data = count_one_second();
+// small_count += ((data << 16) >> 16);
+// large_count += (data >> 16);
+// Serial.print("small counts: ");
+// Serial.print(small_count);
+// Serial.print(" large counts: ");
+// Serial.println(large_count);
+
+
+}
diff --git a/software/README.md b/software/README.md
new file mode 100644
index 0000000..ce2c161
--- /dev/null
+++ b/software/README.md
@@ -0,0 +1,10 @@
+# Software for the Mypart
+
+
+Contains two folders:
++ production. Contains code that responds to button press, wakes up, samples/calculates, and broadcasts over BLE.
++ tests. Contains tests for each individual peripheral, such as the adc, BLE, or led driver.
+
+
+All code is currently currently written for the RFDuino (Nordic NRF51822), using the Arduino IDE.
+
diff --git a/software/production/V0/V0.ino b/software/production/V0/V0.ino
new file mode 100644
index 0000000..1a5fe20
--- /dev/null
+++ b/software/production/V0/V0.ino
@@ -0,0 +1,324 @@
+/*****************************************************************
+*
+* Simple code to interface air particle counter with outside world
+*
+* normally in ULP sleep
+*
+* when awoken, (1) shine lights while fan warms up, (2) dim lights,
+* (3) sample for 5 seconds, (4) shine leds according to numPeaks,
+* (5) broadcast that data for 10 seconds over bluetooth
+*
+* Rundong Tian
+* 9/13/2015
+*
+*****************************************************************/
+
+#include
+#include // need to modify board def to change which are SPI pins
+#include
+#include "TLC59108.h" // 8 channel LED driver
+#include "Adafruit_HDC1000.h" // humidity/temperature sensor
+#include "PCA9536.h" // gpio expander
+
+#include
+#include
+
+Adafruit_HDC1000 hdc = Adafruit_HDC1000(); // init humidty/temp object
+PCA9536 gpio;
+
+//for the 8 leds
+#define I2C_ADDR TLC59108::I2C_ADDR::SUB4
+TLC59108 leds(I2C_ADDR);
+const int numled = 8;
+
+
+const int CS = 3; // SPI cs for ADC
+const int wake = 6; // waking up from ULP
+
+// for gpio
+const int laser = 1;
+const int fan = 2;
+const int ledRST = 0;
+
+// variables for particle counting
+const int small_thresh = 370; // ~.3 Volts
+const int large_thresh = 1500; // ~1.5 Volts
+const int hyst = 10; // maybe for later
+
+// keep track of counts
+int small_count = 0;
+int large_count = 0;
+
+
+// for BLE
+const int interval = 675; // interval (ms) for BLE broadcast 500 - 1000 is sweet spot
+
+/****************************************
+* function to run upon wakeup
+* this function does most of the work.
+* blinks the lights, counts the particles,
+* measures humidity/temperature, yelss out over BLE
+*
+****************************************/
+int onWake(uint32_t ulPin) { // you've been frenched!!!
+
+ RFduino_resetPinWake(wake);
+
+ // turn on the fan and laser
+ gpio.writePin(fan,1);
+ gpio.writePin(laser,1);
+
+ // briefly make some lights as the fan is spinning up
+ leds.init();
+ leds.setLedOutputMode(TLC59108::LED_MODE::PWM_IND);
+
+ uint8_t gap = 130;
+ int zero = 0;
+ leds.setAllBrightness(0xff);
+ delay(gap);
+ leds.setAllBrightness(zero);
+ delay(gap);
+ leds.setAllBrightness(0xff);
+ delay(gap);
+
+ for(int pwm = 0x0ff; pwm >= 0x00; pwm--) {
+ leds.setAllBrightness(pwm);
+ delay(1);
+ }
+
+ fade2zero(8);
+
+ // read the humidity
+ int b = hdc.begin();
+ float temp = hdc.readTemperature();
+ float hum = hdc.readHumidity();
+
+ // reset the number of counts
+
+ small_count = 0;
+ large_count = 0;
+ int total_count = 0;
+ int total_count_prev = 0; // helps us keep track of current led state
+
+
+ // count for 15 seconds
+ for (int i = 0; i < 15; i++) {
+ int data = count_one_second();
+ int data_copy = data;
+
+ small_count += ((data_copy << 16) >> 16);
+ large_count += (data >> 16);
+
+ //shine some lights
+ total_count = small_count; // small count is secretly all counts
+ counts2lights(total_count_prev, total_count); // from, to, wait
+ total_count_prev = total_count;// update prev
+ }
+
+ // turn off all gpios.
+ gpio.writePin(fan,0);
+ gpio.writePin(laser,0);
+
+ char small_str[6] ;
+ char large_str[6] ;
+
+
+
+ sprintf(small_str,"%d",min(small_count - large_count, 999999));
+ sprintf(large_str,"%d",min(large_count, 999999));
+
+ strcat(small_str, ",");
+ strcat(small_str, large_str);
+ // put the two together
+
+ // ble broadcast
+ RFduinoBLE.advertisementData = small_str;
+
+ // start the BLE stack
+ RFduinoBLE.begin();
+ // advertise for ms milliseconds
+ RFduino_ULPDelay(10000);
+ // stop the BLE stack
+ RFduinoBLE.end();
+
+ fade2zero(1);
+ return(0); // go back to sleep
+
+}
+
+
+
+/****************************
+* helper function for mapping the number of particles
+* to light levels
+*****************************/
+void counts2lights(int from, int to) {
+
+ int scale = 10; // scaling the input values to get full range on the lights
+
+ // we have 2047 discrete levels we can represent
+ from = min(from * scale, 2047);
+ to = min(to * scale, 2047);
+
+ for (int i = from; i < to ; i+=32) {
+ uint8_t channel = i/256;
+ uint8_t channel_brightness = i%256;
+ leds.setBrightness(channel, channel_brightness);
+ }
+
+}
+
+/****************************
+* helper function for fadding all of the lights
+* after they commmunicate the number of particles in the air
+*****************************/
+void fade2zero(int wait) {
+
+ // read current light level
+ uint8_t dutyCycles[8];
+ leds.getAllBrightness(dutyCycles);
+
+ // fade from the top
+ for (int i = 7 ; i >= 0 ; i-- ) { // fade from top led
+ for (int j = dutyCycles[i]; j>=0; j--) { // fade each led to zero from it's current value
+ leds.setBrightness(i, j);
+ delay(wait);
+ }
+ }
+
+}
+
+void setup() {
+
+ pinMode(CS, OUTPUT); // must manually toggle CS for nrf51*
+
+ Wire.beginOnPins(1,0);
+ gpio = PCA9536();
+ gpio.configurePins(1, 0, 0, 0); // configure gpio as all output
+ // turn everything off
+ gpio.writePin(3, 0);
+ gpio.writePin(fan, 0);
+ gpio.writePin(laser, 0);
+
+
+ /* setup the wakeup pin */
+ pinMode(wake, INPUT_PULLUP); // configure wakeup pin as input
+ RFduino_pinWakeCallback(wake, LOW, onWake);
+
+ /* set up a few ble parameters */
+ RFduinoBLE.deviceName = "myPart";
+ RFduinoBLE.advertisementInterval = 500; // 500 ms
+ RFduinoBLE.txPowerLevel = 4; //-20 to +4 in 4 dB increments
+
+ RFduino_ULPDelay(INFINITE); // go to sleep forever, until you've been frenched by a handsome prince
+
+}
+
+/*******************
+* Samples for 1 second, reports back big and small counts
+* returns int: large counts as top 16 bits, small counts as lower 16 bits
+* current sample rate:
+********************/
+
+int count_one_second(void)
+{
+
+ unsigned int i = 0;
+ unsigned int lc = 0; // large counts
+ unsigned int sc = 0; // small counts
+ unsigned int particle_check[] = {65535, 65535}; // tiny buffer to check if particles are big enough
+
+ SPI.begin();
+
+ // for now, determine the cutoff count emperically
+ while (i < 87720) { // number of samples determined emperically. Sampling as fast as processing 'algorithm' will allow
+
+ NRF_GPIO->OUTCLR = (1 << CS); // chip select
+
+ //begin spi stuff
+ NRF_SPI0->TXD = 0x0;
+ NRF_SPI0->TXD = 0x0; // double buffer
+
+ /******* first byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ byte data1 = NRF_SPI0->RXD;
+
+ /******* second byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ byte data2 = NRF_SPI0->RXD;
+
+ /******* release CS ***********/
+ NRF_GPIO->OUTSET = (1 << CS); // digitalWrite(CS, HIGH);
+
+ /************ math begin **************************/
+ int data = data2 | (data1 << 8); // concatenate the two things
+ byte curr = i&1;
+ byte prev = (i-1)&1; // TODO: check for corner case at beginning or end of int
+
+ particle_check[curr] = data; // write data into our "circular buffer"
+
+ // check for sizing
+ if ( particle_check[curr] > small_thresh && particle_check[prev] < small_thresh) {
+ sc++;
+ }
+ if ( particle_check[curr] > large_thresh && particle_check[prev] < large_thresh) {
+ lc++;
+ }
+
+ i++;
+
+ } // end while
+
+ SPI.end();
+ return (lc << 16) | sc; // large counts (lc) as top 16 bits, sc as lower 16 bits
+
+
+}
+
+
+/********************************************
+* Timer configuration for 20us sampling period
+*********************************************/
+void timer_1_config(void)
+{
+ NRF_TIMER1->TASKS_STOP = 1; // Stop timer
+ NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; // fancy name for 0 (timer mode
+ NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);
+ NRF_TIMER1->PRESCALER = 4; // SysClk/2^PRESCALER) = 16,000,000/16 = 1us resolution
+ NRF_TIMER1->TASKS_CLEAR = 1; // Clear TIMER
+ NRF_TIMER1->CC[0] = 20; // 20 us capture/compare register
+ NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; // set interrupt enable in the compare[0] position
+ NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
+
+ NRF_TIMER1->TASKS_START = 1; // Start TIMER
+}
+
+/***************************
+* Timer interrupt, potentially used for sampling at a more consistent rate
+*
+****************************/
+void TIMER1_IRQHandler(void)
+{
+
+ if (NRF_TIMER1->EVENTS_COMPARE[0] != 0) // for the 20us timer
+ {
+
+ NRF_TIMER1->EVENTS_COMPARE[0] = 0; // clear the register
+ }
+}
+
+void loop() { // nothing in loop
+// int data = count_one_second();
+// small_count += ((data << 16) >> 16);
+// large_count += (data >> 16);
+// Serial.print("small counts: ");
+// Serial.print(small_count);
+// Serial.print(" large counts: ");
+// Serial.println(large_count);
+
+
+}
diff --git a/software/tests/ble_interval/ble_interval.ino b/software/tests/ble_interval/ble_interval.ino
new file mode 100644
index 0000000..f041795
--- /dev/null
+++ b/software/tests/ble_interval/ble_interval.ino
@@ -0,0 +1,86 @@
+/*
+The sketch demonstrates how to increase or decrease the Bluetooth Low Energy 4
+Advertisement transmission interval.
+
+Faster iterval = higher power consumption = lower connection latency
+*/
+
+/*
+ Copyright (c) 2014 OpenSourceRF.com. All right reserved.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include
+
+
+// pin 3 on the RGB shield is the green led
+int led = 3;
+
+// interval between advertisement transmissions ms (range is 20ms to 10.24s) - default 20ms
+int interval = 500; // 675 ms between advertisement transmissions
+
+void setup() {
+ // led used to indicate that the RFduino is advertising
+ pinMode(led, OUTPUT);
+
+ // this is the data we want to appear in the advertisement
+ // (if the deviceName and advertisementData are too long to fix into the 31 byte
+ // ble advertisement packet, then the advertisementData is truncated first down to
+ // a single byte, then it will truncate the deviceName)
+ RFduinoBLE.deviceName = "myPart";
+
+
+ // change the advertisement interval
+ RFduinoBLE.advertisementInterval = interval;
+
+
+}
+
+void loop() {
+ // start the BLE stack
+
+ int i = 0;
+
+ while (true) {
+
+ i ++ ; // send some new data every time
+ RFduinoBLE.advertisementData = (char*) (i);
+
+ RFduinoBLE.begin();
+ delay(10000); // stop advertising
+ RFduinoBLE.end();
+ }
+
+}
+
+void RFduinoBLE_onAdvertisement(bool start)
+{
+ // turn the green led on if we start advertisement, and turn it
+ // off if we stop advertisement
+
+ if (start)
+ digitalWrite(led, HIGH);
+ else
+ digitalWrite(led, LOW);
+}
diff --git a/software/tests/humidity_test/humidity_test.ino b/software/tests/humidity_test/humidity_test.ino
new file mode 100644
index 0000000..486df2f
--- /dev/null
+++ b/software/tests/humidity_test/humidity_test.ino
@@ -0,0 +1,39 @@
+/***************************************************
+ This is an example for the HDC100x Humidity & Temp Sensor
+
+ Designed specifically to work with the HDC1000 sensor from Adafruit
+ ----> https://www.adafruit.com/products/2635
+
+ These sensors use I2C to communicate, 2 pins are required to
+ interface
+ ****************************************************/
+
+#include
+#include "Adafruit_HDC1000.h"
+
+// Connect Vin to 3-5VDC
+// Connect GND to ground
+// Connect SCL to I2C clock pin (A5 on UNO)
+// Connect SDA to I2C data pin (A4 on UNO)
+
+Adafruit_HDC1000 hdc = Adafruit_HDC1000();
+
+void setup() {
+ Serial.begin(9600);
+}
+
+
+void loop() {
+
+ if (!hdc.begin()) {
+ while (1) {
+ Serial.println("Couldn't find sensor!");
+ delay(500);
+ }
+
+ }
+
+ Serial.print("Temp: "); Serial.print(hdc.readTemperature());
+ Serial.print("\t\tHum: "); Serial.println(hdc.readHumidity());
+ delay(500);
+}
diff --git a/software/tests/i2c_gpio_test/i2c_gpio_test.ino b/software/tests/i2c_gpio_test/i2c_gpio_test.ino
new file mode 100644
index 0000000..e73e9f9
--- /dev/null
+++ b/software/tests/i2c_gpio_test/i2c_gpio_test.ino
@@ -0,0 +1,34 @@
+
+#include
+#include "PCA9536.h"
+
+PCA9536 gpio;
+
+void setup() {
+ Wire.beginOnPins(1,0);
+
+ gpio = PCA9536();
+ gpio.configurePins(0, 0, 0, 0); // configure all as output
+
+
+
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ gpio.writePin(3, 1);
+ gpio.writePin(2, 1);
+ gpio.writePin(1, 1);
+ gpio.writePin(0, 1);
+
+ delay(50);
+
+ gpio.writePin(3, 0);
+ gpio.writePin(2, 0);
+ gpio.writePin(1, 0);
+ gpio.writePin(0, 0);
+
+ delay(50);
+
+
+}
diff --git a/software/tests/i2c_lights_test/i2c_lights_test.ino b/software/tests/i2c_lights_test/i2c_lights_test.ino
new file mode 100644
index 0000000..f55da50
--- /dev/null
+++ b/software/tests/i2c_lights_test/i2c_lights_test.ino
@@ -0,0 +1,47 @@
+#include
+
+#include "TLC59108.h"
+
+#define HW_RESET_PIN 2
+#define I2C_ADDR TLC59108::I2C_ADDR::SUB4
+
+TLC59108 leds(I2C_ADDR);
+
+void setup() {
+ Wire.begin();
+ leds.init(HW_RESET_PIN);
+ leds.setLedOutputMode(TLC59108::LED_MODE::PWM_IND);
+}
+
+void loop(){
+ sweep();
+}
+
+void sweep() {
+ byte pwm;
+
+ for(pwm = 0; pwm < 0xff; pwm++) {
+ leds.setAllBrightness(pwm);
+ delay(10);
+ }
+
+ for(pwm = 0xfe; pwm < 0xff; pwm--) {
+ leds.setAllBrightness(pwm);
+ delay(10);
+ }
+
+ for(byte channel = 0; channel < 8; channel++)
+ for(pwm = 0; pwm < 0xff; pwm++) {
+ leds.setBrightness(channel, pwm);
+ delay(10);
+ }
+
+ for(byte channel = 0; channel < 8; channel++)
+ for(pwm = 0xfe; pwm < 0xff; pwm--) {
+ leds.setBrightness(channel, pwm);
+ delay(10);
+ }
+}
+
+
+
diff --git a/software/tests/i2c_scanner/i2c_scanner.ino b/software/tests/i2c_scanner/i2c_scanner.ino
new file mode 100644
index 0000000..0e89238
--- /dev/null
+++ b/software/tests/i2c_scanner/i2c_scanner.ino
@@ -0,0 +1,85 @@
+// --------------------------------------
+// i2c_scanner
+//
+// Version 1
+// This program (or code that looks like it)
+// can be found in many places.
+// For example on the Arduino.cc forum.
+// The original author is not know.
+// Version 2, Juni 2012, Using Arduino 1.0.1
+// Adapted to be as simple as possible by Arduino.cc user Krodal
+// Version 3, Feb 26 2013
+// V3 by louarnold
+// Version 4, March 3, 2013, Using Arduino 1.0.3
+// by Arduino.cc user Krodal.
+// Changes by louarnold removed.
+// Scanning addresses changed from 0...127 to 1...119,
+// according to the i2c scanner by Nick Gammon
+// http://www.gammon.com.au/forum/?id=10896
+// Version 5, March 28, 2013
+// As version 4, but address scans now to 127.
+// A sensor seems to use address 120.
+// Version ThomasOlson 20140527.1 works with RFduino with mods.
+//
+// This sketch tests the standard 7-bit addresses
+// Devices with higher bit address might not be seen properly.
+//
+
+#include
+
+
+void setup()
+{
+ Wire.begin();
+
+ Serial.begin(115200);
+ Serial.println("\nI2C Scanner");
+}
+
+
+void loop()
+{
+ byte error, address;
+ int nDevices;
+
+ Serial.println("Scanning...");
+
+ nDevices = 0;
+
+ for(address = 1; address < 127; address++ )
+ {
+ // The i2c_scanner uses the return value of
+ // the Write.endTransmisstion to see if
+ // a device did acknowledge to the address.
+ Wire.beginTransmission(address);
+ Wire.write(0x00);
+ error = Wire.endTransmission();
+
+ if (error == 0)
+ {
+ Serial.print("I2C device found at address 0x");
+ if (address<16)
+ Serial.print("0");
+ Serial.print(address,HEX);
+ Serial.println(" !");
+
+ nDevices++;
+ //}else if (error==4)
+ }else{
+ Serial.print("Error ");
+ Serial.print(error);
+ Serial.print(" at address 0x");
+ if (address<16)
+ Serial.print("0");
+ Serial.println(address,HEX);
+ }
+ }
+
+ if (nDevices == 0){
+ Serial.println("No I2C devices found\n");
+ }else{
+ Serial.print(nDevices);
+ Serial.println(" found\n");
+ }
+ delay(5000); // wait 5 seconds for next scan
+}
diff --git a/software/tests/spi_adc/spi_adc.ino b/software/tests/spi_adc/spi_adc.ino
new file mode 100644
index 0000000..c680b3b
--- /dev/null
+++ b/software/tests/spi_adc/spi_adc.ino
@@ -0,0 +1,34 @@
+
+#include
+
+// works, but not gapless transfer between the two bytes, and links to other library
+
+const int CS = 2;
+
+void setup() {
+
+ // default configuratino of SPI bus is 4MHz
+
+ Serial.begin(9600);
+ pinMode(CS, OUTPUT);
+}
+
+void loop() {
+
+ byte data1 = 0xde;
+ byte data2 = 0xad;
+
+
+ SPI.begin();
+ digitalWrite(CS, LOW);
+ byte return1 = SPI.transfer(data1);
+ byte return2 = SPI.transfer(data2);
+
+ digitalWrite(CS, HIGH);
+ Serial.println(return1);
+ Serial.println(return2);
+
+ delay(500);
+
+
+}
diff --git a/software/tests/spi_adc_inline/spi_adc_inline.ino b/software/tests/spi_adc_inline/spi_adc_inline.ino
new file mode 100644
index 0000000..1c8e4e6
--- /dev/null
+++ b/software/tests/spi_adc_inline/spi_adc_inline.ino
@@ -0,0 +1,56 @@
+
+//register calls for back to back (double buffered) spi read
+
+
+#include
+
+const int CS = 2;
+
+void setup() {
+
+ // default configuratino of SPI bus is 4MHz
+
+ Serial.begin(9600);
+ pinMode(CS, OUTPUT); // must manually toggle CS for nrf51*
+
+ SPI.begin();
+
+}
+
+void loop() {
+
+ byte data1;
+ byte data2;
+ unsigned short data;
+
+ NRF_GPIO->OUTCLR = (1 << CS);
+
+
+
+ //begin spi stuff
+ NRF_SPI0->TXD = 0x0;
+ NRF_SPI0->TXD = 0x0; // double buffer
+
+ // first byte
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ data1 = NRF_SPI0->RXD;
+
+ // second byte
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ data2 = NRF_SPI0->RXD;
+
+
+ NRF_GPIO->OUTSET = (1 << CS); // digitalWrite(CS, HIGH);
+
+ data = data2 | (data1 << 8); // concatenate the two things
+
+ Serial.print("all bits: ");
+ Serial.println(data);
+
+
+
+}
diff --git a/software/tests/spi_adc_inline_and_math/spi_adc_inline_and_math.ino b/software/tests/spi_adc_inline_and_math/spi_adc_inline_and_math.ino
new file mode 100644
index 0000000..522d5eb
--- /dev/null
+++ b/software/tests/spi_adc_inline_and_math/spi_adc_inline_and_math.ino
@@ -0,0 +1,94 @@
+// adc sampling, and do math for peak detection
+
+
+#include
+
+
+
+const int CS = 2;
+const int testPin = 6;
+const int small_thresh = 1000;
+const int large_thresh = 2000;
+int sc = 0; // small count
+int lc = 0; // large count
+unsigned int particle_check[] = {65535, 65535}; // used to check if particles pass a threshold
+unsigned int i = 0;
+
+void setup() {
+
+ // default configuratino of SPI bus is 4MHz
+
+ Serial.begin(9600);
+ pinMode(CS, OUTPUT); // must manually toggle CS for nrf51*
+ pinMode(testPin, OUTPUT);
+ NRF_GPIO->OUTCLR = (1 << testPin); // set init state of testpin
+ SPI.begin();
+
+}
+
+void loop() {
+
+
+
+ byte data1;
+ byte data2;
+ unsigned short data;
+
+ NRF_GPIO->OUTCLR = (1 << CS);
+
+ //begin spi stuff
+ NRF_SPI0->TXD = 0x0;
+ NRF_SPI0->TXD = 0x0; // double buffer
+
+ /******* first byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ data1 = NRF_SPI0->RXD;
+
+ /******* second byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ data2 = NRF_SPI0->RXD;
+
+ /******* release CS ***********/
+ NRF_GPIO->OUTSET = (1 << CS); // digitalWrite(CS, HIGH);
+
+
+
+ /************ math begin **************************/
+
+ NRF_GPIO->OUTSET = (1 << testPin); // start timing
+ data = data2 | (data1 << 8); // concatenate the two things
+ int curr = i&1;
+ int prev = (i-1)&1;
+ particle_check[curr] = data; // write data into our circular buffer
+
+ if ( particle_check[curr] > small_thresh && particle_check[prev] < small_thresh) {
+ sc++;
+ }
+
+ if ( particle_check[curr] > large_thresh && particle_check[prev] < large_thresh) {
+ lc++;
+ }
+
+ i++;
+
+ // for timing
+ NRF_GPIO->OUTCLR = (1 << testPin);
+
+
+//
+// Serial.print("small count: ");
+// Serial.println(sc);
+// Serial.print("large count: ");
+// Serial.println(lc);
+//
+//
+//
+//
+// delay(500);
+
+
+}
diff --git a/software/tests/timer_adc_simple/timer_adc_simple.ino b/software/tests/timer_adc_simple/timer_adc_simple.ino
new file mode 100644
index 0000000..6b4b94d
--- /dev/null
+++ b/software/tests/timer_adc_simple/timer_adc_simple.ino
@@ -0,0 +1,101 @@
+
+
+// triggering adc samples with timer interrupts
+
+
+#include
+
+
+const int testPin = 6;
+const int CS = 2;
+
+const int small_thresh = 1000;
+const int large_thresh = 2000;
+
+/******* variables accessed in ISR *************/
+volatile int sc = 0; // small count
+volatile int lc = 0; // large count
+
+volatile unsigned int particle_check[] = {65535, 65535}; // used to check if particles pass a threshold
+volatile unsigned int i = 0;
+
+
+
+
+void setup() {
+
+ timer_1_config(); // configure some shit
+
+ pinMode(testPin, OUTPUT);
+ pinMode(CS, OUTPUT); // must manually toggle CS for nrf51*
+ SPI.begin();
+
+
+}
+
+
+void timer_1_config(void)
+{
+ NRF_TIMER1->TASKS_STOP = 1; // Stop timer
+ NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; // (TIMER_MODE_MODE_Timer = 1) => for timer mode
+ NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);
+ NRF_TIMER1->PRESCALER = 4; // SysClk/2^PRESCALER) = 16,000,000/16 = 1us resolution
+ NRF_TIMER1->TASKS_CLEAR = 1; // Clear timer
+ NRF_TIMER1->CC[0] = 26; // 20 us
+ NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; // set up an interrupt for CC[0]
+ NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
+ attachInterrupt(TIMER1_IRQn, TIMER1_IRQHandler); // also used in variant.cpp to configure the RTC1
+ NRF_TIMER1->TASKS_START = 1; // Start TIMER
+}
+
+
+void TIMER1_IRQHandler(void)
+{
+ if (NRF_TIMER1->EVENTS_COMPARE[0] != 0)
+ {
+
+ NRF_GPIO->OUTCLR = (1 << CS); // activate CS
+
+ //begin spi stuff
+ NRF_SPI0->TXD = 0x0;
+ NRF_SPI0->TXD = 0x0; // double buffer
+
+ /******* first byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ byte data1 = NRF_SPI0->RXD;
+ /******* second byte ***********/
+ while (NRF_SPI0->EVENTS_READY == 0)
+ ;
+ NRF_SPI0->EVENTS_READY = 0;
+ byte data2 = NRF_SPI0->RXD;
+ /********** release cs **********/
+ NRF_GPIO->OUTSET = (1 << CS);
+
+ unsigned short data = data2 | (data1 << 8); // concatenate the two things
+
+ /************ math begin **************************/
+
+ int curr = i&1;
+ int prev = (i-1)&1;
+ particle_check[curr] = data;
+
+ if ( particle_check[curr] > small_thresh && particle_check[prev] < small_thresh) {
+ sc++;
+ }
+
+ if ( particle_check[curr] > large_thresh && particle_check[prev] < large_thresh) {
+ lc++;
+ }
+
+ i++; // increment our index
+
+ NRF_TIMER1->EVENTS_COMPARE[0] = 0; // clear the interrupt (use shorts to not have to do this?
+
+ }
+}
+
+void loop() {
+ // nothing to see here
+}
diff --git a/software/tests/timer_interrupts/timer_interrupts.ino b/software/tests/timer_interrupts/timer_interrupts.ino
new file mode 100644
index 0000000..34e9da5
--- /dev/null
+++ b/software/tests/timer_interrupts/timer_interrupts.ino
@@ -0,0 +1,45 @@
+
+
+const int testPin = 6;
+
+
+void setup() {
+
+ timer_config();
+ pinMode(testPin, OUTPUT);
+
+
+}
+
+
+void timer_config(void)
+{
+ NRF_TIMER1->TASKS_STOP = 1; // Stop timer
+ NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; // (TIMER_MODE_MODE_Timer = 1) => for timer mode
+ NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);
+ NRF_TIMER1->PRESCALER = 4; // SysClk/2^PRESCALER) = 16,000,000/16 = 1us resolution
+ NRF_TIMER1->TASKS_CLEAR = 1; // Clear timer
+ NRF_TIMER1->CC[0] = 20; // 20 us
+ NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; // set up an interrupt for CC[0]
+ NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
+ attachInterrupt(TIMER1_IRQn, TIMER1_Interrupt); // also used in variant.cpp to configure the RTC1
+ NRF_TIMER1->TASKS_START = 1; // Start TIMER
+}
+
+
+void TIMER1_Interrupt(void)
+{
+ if (NRF_TIMER1->EVENTS_COMPARE[0] != 0)
+ {
+
+ NRF_GPIO->OUTSET = (1 << testPin); // toggle some pins
+ delayMicroseconds(5);
+ NRF_GPIO->OUTCLR = (1 << testPin);
+
+ NRF_TIMER1->EVENTS_COMPARE[0] = 0; // clear the event
+ }
+}
+
+void loop() {
+ // nothing to see here
+}
diff --git a/software/tests/timer_interrupts_for_adc/timer_interrupts_for_adc.ino b/software/tests/timer_interrupts_for_adc/timer_interrupts_for_adc.ino
new file mode 100644
index 0000000..264d5b5
--- /dev/null
+++ b/software/tests/timer_interrupts_for_adc/timer_interrupts_for_adc.ino
@@ -0,0 +1,108 @@
+
+
+#include
+const int CS = 2;
+const int testPin = 6;
+const int small_thresh = 1000;
+const int large_thresh = 2000;
+
+
+volatile int sc = 0; // small count
+volatile int lc = 0; // large count
+
+volatile unsigned int particle_check[] = {65535, 65535}; // used to check if particles pass a threshold
+volatile unsigned int i = 0;
+
+void setup() {
+
+ timer_1_config();
+
+ Serial.begin(115200);
+ pinMode(CS, OUTPUT); // must manually toggle CS for nrf51*
+ pinMode(testPin, OUTPUT);
+ NRF_GPIO->OUTCLR = (1 << testPin); // set init state of testpin
+// SPI.begin();
+
+}
+
+/********************************************
+* Timer configuration for 20us sampling period
+*********************************************/
+void timer_1_config(void)
+{
+ NRF_TIMER1->TASKS_STOP = 1; // Stop timer
+ NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; // fancy name for 0 (timer mode
+ NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos);
+ NRF_TIMER1->PRESCALER = 4; // SysClk/2^PRESCALER) = 16,000,000/16 = 1us resolution
+ NRF_TIMER1->TASKS_CLEAR = 1; // Clear TIMER
+ NRF_TIMER1->CC[0] = 20; // 20 us capture/compare register
+ NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; // set interrupt enable in the compare[0] position
+ NRF_TIMER1->SHORTS = (TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos);
+
+ NRF_TIMER1->TASKS_START = 1; // Start TIMER
+}
+
+/***************************
+* Our sampling interrupt
+*
+****************************/
+void TIMER1_IRQHandler(void)
+{
+
+ if (NRF_TIMER1->EVENTS_COMPARE[0] != 0) // for the 20us timer
+ {
+
+ NRF_GPIO->OUTCLR = (1 << CS);
+ delay(5);
+ NRF_GPIO->OUTSET = (1 << CS);
+
+
+// NRF_GPIO->OUTCLR = (1 << CS);
+//
+// //begin spi stuff
+// NRF_SPI0->TXD = 0x0;
+// NRF_SPI0->TXD = 0x0; // double buffer
+//
+// /******* first byte ***********/
+// while (NRF_SPI0->EVENTS_READY == 0)
+// ;
+// NRF_SPI0->EVENTS_READY = 0;
+// byte data1 = NRF_SPI0->RXD;
+//
+// /******* second byte ***********/
+// while (NRF_SPI0->EVENTS_READY == 0)
+// ;
+// NRF_SPI0->EVENTS_READY = 0;
+// byte data2 = NRF_SPI0->RXD;
+//
+// /******* release CS ***********/
+// NRF_GPIO->OUTSET = (1 << CS); // digitalWrite(CS, HIGH);
+//
+// /************ math begin **************************/
+//
+// NRF_GPIO->OUTSET = (1 << testPin); // start timing
+// int data = data2 | (data1 << 8); // concatenate the two things
+// byte curr = i&1;
+// byte prev = (i-1)&1;
+// particle_check[curr] = data; // write data into our circular buffer
+//
+// if ( particle_check[curr] > small_thresh && particle_check[prev] < small_thresh) {
+// sc++;
+// }
+//
+// if ( particle_check[curr] > large_thresh && particle_check[prev] < large_thresh) {
+// lc++;
+// }
+//
+// i++;
+//
+
+ NRF_TIMER1->EVENTS_COMPARE[0] = 0;
+ }
+}
+
+void loop() {
+
+
+
+}