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() { + + + +}