From 61bf787234eb5b5bfee6eccdc6f000656326d4f0 Mon Sep 17 00:00:00 2001
From: Sam Calisch <s.calisch@gmail.com>
Date: Wed, 1 Nov 2017 09:08:30 -0400
Subject: [PATCH] added firmware

---
 nrf52-stepper/index.html                      | 134 ++++++++++++++++++
 nrf52-stepper/nrf52-drv8825/nrf52-drv8825.ino | 133 +++++++++++------
 nrf52-stepper/nrf52-drv8825/radio.h           | 114 +++++++++++++++
 3 files changed, 340 insertions(+), 41 deletions(-)
 create mode 100644 nrf52-stepper/nrf52-drv8825/radio.h

diff --git a/nrf52-stepper/index.html b/nrf52-stepper/index.html
index 7c56394..f9df329 100644
--- a/nrf52-stepper/index.html
+++ b/nrf52-stepper/index.html
@@ -1,8 +1,142 @@
 <html>
+<head>
+<style>
+pre code {
+  background-color: #eee;
+  border: 1px solid #999;
+  display: block;
+  padding: 20px;
+}
+</style>
+</head>
 <body>
+<h1>nRF52 + DRV8825 Stepper Driver</h1>
+
 <a href='nrf52-stepper-layout.png'><img src='nrf52-stepper-layout.png' height=300px></a>
 <a href='nrf52-stepper-traces.png'><img src='nrf52-stepper-traces.png' height=300px></a>
 <a href='nrf52-stepper-interior.png'><img src='nrf52-stepper-interior.png' height=300px></a>
 <p>This is a stepper motor controller built around the DRV8825 and the nRF52.</p>
+
+<p>Some sample firmware is available below (or as files: <a href='nrf52-drv8825/nrf52-drv8825.ino'>nrf52-drv8825.ino</a> and <a href='nrf52-drv8825/radio.h'>radio.h</a>).  This code defines a command set issued over the radio for moving a number of steps, changing stepping speed, setting microstepping parameters, and setting a current limit value.</p>
+
+<pre>
+<code>
+#include "radio.h"
+uint16_t pwms[1] = {0};
+uint16_t step_period = 20000; //microseconds
+
+const uint8_t pin_mode1 = 3; //A1
+const uint8_t pin_mode0 = 0; //XL1
+const uint8_t pin_step = 1; //XL2
+const uint8_t pin_direction = 2; //A0
+const uint8_t pin_nrst = 27; //p27
+const uint8_t pin_ref = 26; //p26
+
+int i=0; //counter
+
+void stepper_setup(){
+  NRF_GPIO->DIRSET = (1 << pin_nrst); //set nrst/nslp pins as output
+  NRF_GPIO->OUTCLR = (1 << pin_nrst); //set nrst/nslp low to disable drv8825
+  NRF_GPIO->OUT = (0 << pin_nrst);
+
+  NRF_GPIO->DIRSET = (1 << pin_mode1) | (1 << pin_mode0); //set mode pins as output
+  NRF_GPIO->OUTCLR = (1 << pin_mode1) | (1 << pin_mode0); //set to full step mode
+
+  NRF_GPIO->DIRSET = (1 << pin_step) | (1 << pin_direction); //set step/dir pins as output
+
+  //Use PWM module to generate aref/bref
+  NRF_GPIO->DIRSET = (1 << pin_ref); //set ref pin as output
+  NRF_GPIO->OUTCLR = (1 << pin_ref); //set ref pin low
+  NRF_PWM0->PSEL.OUT[0] = (pin_ref << PWM_PSEL_OUT_PIN_Pos) | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos); //set aref pin to pwm out[0]
+  NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
+  NRF_PWM0->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos);
+  NRF_PWM0->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 << PWM_PRESCALER_PRESCALER_Pos); //16MHz tick
+  NRF_PWM0->COUNTERTOP = (1600 << PWM_COUNTERTOP_COUNTERTOP_Pos); //10 kHz pwm freq.
+  NRF_PWM0->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos);
+  NRF_PWM0->DECODER = (PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) | (PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);
+  pwms[0] = 1600-100; //100/1600 * 3.3v = .2V = 200 mA limit
+  NRF_PWM0->SEQ[0].PTR = ((uint32_t)(pwms) << PWM_SEQ_PTR_PTR_Pos);
+  NRF_PWM0->SEQ[0].CNT = (1 << PWM_SEQ_CNT_CNT_Pos);
+  NRF_PWM0->SEQ[0].REFRESH = 0;
+  NRF_PWM0->SEQ[0].ENDDELAY = 0;
+  NRF_PWM0->TASKS_SEQSTART[0] = 1;
+  delay(1); //give aref filter time to settle.
+}
+
+void parse_command(){
+  //interpret command from radio for stepper actions
+  if( radio_buffer[0] == 1 ){
+    //move by commanded number of steps
+    if (radio_buffer[1] > 0){
+      NRF_GPIO->OUTSET = (1 << pin_direction); //set direction forwards      
+    } else {
+      NRF_GPIO->OUTCLR = (1 << pin_direction); //set direction backwards    
+    }
+    radio_buffer[1] = radio_buffer[1] > 0 ? radio_buffer[1] : -radio_buffer[1];
+    for(i=0; i < radio_buffer[1]; i++){
+      NRF_GPIO->OUTSET = (1 << pin_step);
+      delayMicroseconds(step_period);
+      NRF_GPIO->OUTCLR = (1 << pin_step);
+      delayMicroseconds(10);        
+    }
+  } else if (radio_buffer[0] == 2){
+    //change step speed
+    step_period = radio_buffer[1];
+  } else if (radio_buffer[0] == 3){
+    //change microstepping
+    if (radio_buffer[1] & 1){ 
+      NRF_GPIO->OUTSET = (1 << pin_mode0);
+    } else {
+      NRF_GPIO->OUTCLR = (1 << pin_mode0);      
+    }
+    if (radio_buffer[1] & 2){ 
+      NRF_GPIO->OUTSET = (1 << pin_mode1);
+    } else {
+      NRF_GPIO->OUTCLR = (1 << pin_mode1);      
+    }
+  } else if (radio_buffer[0] == 4){
+    //change current limit
+    pwms[0] = 1600-radio_buffer[1]; //100/1600 * 3.3v = .2V = 200 mA limit
+    NRF_PWM0->SEQ[0].REFRESH = 1;
+  }
+  else{
+  }
+
+  //unrecognized command, set radio buffer to all -1
+  //for(int i=0; i < PACKET_LENGTH; i++){
+  //  radio_buffer[i] = -1;
+  //}      
+
+  //reset radio buffer
+  for(i=0; i < PACKET_LENGTH; i++){
+    radio_buffer[i] = 0;
+  }
+}
+
+
+void setup() {
+  
+  //Switch to internal LFCLK to disconnect from XL1 and XL2
+  NRF_CLOCK->LFCLKSRC = 0; //disconnect XL1 AND XL2 FROM LFCLK
+  NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
+  NRF_CLOCK->TASKS_LFCLKSTART    = 1;
+  while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {}
+
+  stepper_setup();
+  radio_setup();
+
+  NRF_GPIO->OUTSET = (1 << pin_nrst); //set nrst/nslp high to enable drv8825
+
+  while (true) {
+    int result = radio_recv(); //wait until recieve
+    parse_command(); 
+  }
+}
+
+void loop() {}
+
+</code>
+</pre>
+
 </body>
 </html>
\ No newline at end of file
diff --git a/nrf52-stepper/nrf52-drv8825/nrf52-drv8825.ino b/nrf52-stepper/nrf52-drv8825/nrf52-drv8825.ino
index 4183de5..1e79dd0 100644
--- a/nrf52-stepper/nrf52-drv8825/nrf52-drv8825.ino
+++ b/nrf52-stepper/nrf52-drv8825/nrf52-drv8825.ino
@@ -1,5 +1,6 @@
-
+#include "radio.h"
 uint16_t pwms[1] = {0};
+uint16_t step_period = 20000; //microseconds
 
 const uint8_t pin_mode1 = 3; //A1
 const uint8_t pin_mode0 = 0; //XL1
@@ -8,77 +9,127 @@ const uint8_t pin_direction = 2; //A0
 const uint8_t pin_nrst = 27; //p27
 const uint8_t pin_ref = 26; //p26
 
+int i=0; //counter
 
-
-void setup() {
-
-  Serial.begin(115200);
+void stepper_setup(){
   NRF_GPIO->DIRSET = (1 << pin_nrst); //set nrst/nslp pins as output
   NRF_GPIO->OUTCLR = (1 << pin_nrst); //set nrst/nslp low to disable drv8825
   NRF_GPIO->OUT = (0<<pin_nrst);
-  
-  //Switch to internal LFCLK to disconnect from XL1 and XL2
-  NRF_CLOCK->LFCLKSRC = 0; //disconnect XL1 AND XL2 FROM LFCLK?
-  NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
-  NRF_CLOCK->TASKS_LFCLKSTART    = 1;
-  while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {}
 
   NRF_GPIO->DIRSET = (1 << pin_mode1) | (1 << pin_mode0); //set mode pins as output
   NRF_GPIO->OUTCLR = (1 << pin_mode1) | (1 << pin_mode0); //set to full step mode
 
   NRF_GPIO->DIRSET = (1 << pin_step) | (1 << pin_direction); //set step/dir pins as output
-  
-  
-  //NRF_TIMER1->MODE = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk;
-  //NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos) & TIMER_BITMODE_BITMODE_Msk;
-  //NRF_TIMER1->PRESCALER = (7 << TIMER_PRESCALER_PRESCALER_Pos) & TIMER_PRESCALER_PRESCALER_Msk;
-  //NRF_TIMER1->SHORTS = ((TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos) & TIMER_SHORTS_COMPARE0_CLEAR_Msk);
-  //NRF_TIMER1->CC[0] = (1 << 15); //50% duty cycle to test
 
-  //enable PPI channel 0 for compare task setting pin high
-  //NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) & PPI_CHEN_CH0_Msk;
-  //NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
-  //NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
-  //enable PPI channel 1 for compare overflow setting pin low
-  //NRF_PPI->CHEN = (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos) & PPI_CHEN_CH1_Msk;
-  //NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER1->EVENTS_;
-  //NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[1];
-
-  //NRF_TIMER1->TASKS_START = 1;  //start timer
-
-  //Use PWM module
+  //Use PWM module to generate aref/bref
   NRF_GPIO->DIRSET = (1<<pin_ref); //set ref pin as output
   NRF_GPIO->OUTCLR = (1<<pin_ref); //set ref pin low
   NRF_PWM0->PSEL.OUT[0] = (pin_ref << PWM_PSEL_OUT_PIN_Pos) | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos); //set aref pin to pwm out[0]
   NRF_PWM0->ENABLE = (PWM_ENABLE_ENABLE_Enabled << PWM_ENABLE_ENABLE_Pos);
   NRF_PWM0->MODE = (PWM_MODE_UPDOWN_Up << PWM_MODE_UPDOWN_Pos);
   NRF_PWM0->PRESCALER = (PWM_PRESCALER_PRESCALER_DIV_1 << PWM_PRESCALER_PRESCALER_Pos); //16MHz tick
-  NRF_PWM0->COUNTERTOP = (1600 << PWM_COUNTERTOP_COUNTERTOP_Pos); //1 kHz pwm freq.
+  NRF_PWM0->COUNTERTOP = (1600 << PWM_COUNTERTOP_COUNTERTOP_Pos); //10 kHz pwm freq.
   NRF_PWM0->LOOP = (PWM_LOOP_CNT_Disabled << PWM_LOOP_CNT_Pos);
   NRF_PWM0->DECODER = (PWM_DECODER_LOAD_Common << PWM_DECODER_LOAD_Pos) | (PWM_DECODER_MODE_RefreshCount << PWM_DECODER_MODE_Pos);
-  pwms[0] = 1500; //50% duty cycle to test
-  delay(1);
+  pwms[0] = 1600-100; //100/1600 * 3.3v = .2V = 200 mA limit
   NRF_PWM0->SEQ[0].PTR = ((uint32_t)(pwms) << PWM_SEQ_PTR_PTR_Pos);
   NRF_PWM0->SEQ[0].CNT = (1 << PWM_SEQ_CNT_CNT_Pos);
   NRF_PWM0->SEQ[0].REFRESH = 0;
   NRF_PWM0->SEQ[0].ENDDELAY = 0;
   NRF_PWM0->TASKS_SEQSTART[0] = 1;
-  
   delay(1); //give aref filter time to settle.
+}
+
+void parse_command(){
+  //interpret command from radio for stepper actions
+  if( radio_buffer[0] == 1 ){
+    //move by commanded number of steps
+    if (radio_buffer[1] > 0){
+      NRF_GPIO->OUTSET = (1<<pin_direction); //set direction forwards      
+    } else {
+      NRF_GPIO->OUTCLR = (1<<pin_direction); //set direction backwards    
+    }
+    radio_buffer[1] = radio_buffer[1] > 0 ? radio_buffer[1] : -radio_buffer[1];
+    for(i=0; i<radio_buffer[1]; i++){
+      NRF_GPIO->OUTSET = (1<<pin_step);
+      delayMicroseconds(step_period);
+      NRF_GPIO->OUTCLR = (1<<pin_step);
+      delayMicroseconds(10);        
+    }
+  } else if (radio_buffer[0] == 2){
+    //change step speed
+    step_period = radio_buffer[1];
+  } else if (radio_buffer[0] == 3){
+    //change microstepping
+    if (radio_buffer[1] & 1){ 
+      NRF_GPIO->OUTSET = (1 << pin_mode0);
+    } else {
+      NRF_GPIO->OUTCLR = (1 << pin_mode0);      
+    }
+    if (radio_buffer[1] & 2){ 
+      NRF_GPIO->OUTSET = (1 << pin_mode1);
+    } else {
+      NRF_GPIO->OUTCLR = (1 << pin_mode1);      
+    }
+  } else if (radio_buffer[0] == 4){
+    //change current limit
+    pwms[0] = 1600-radio_buffer[1]; //100/1600 * 3.3v = .2V = 200 mA limit
+    NRF_PWM0->SEQ[0].REFRESH = 1;
+  }
+  else{
+  }
+
+  //unrecognized command, set radio buffer to all -1
+  //for(int i=0; i<PACKET_LENGTH; i++){
+  //  radio_buffer[i] = -1;
+  //}      
+
+  //reset radio buffer
+  for(i=0; i<PACKET_LENGTH; i++){
+    radio_buffer[i] = 0;
+  }
+}
+
+
+void setup() {
+
+  //Serial.begin(115200);
+  
+  //Switch to internal LFCLK to disconnect from XL1 and XL2
+  NRF_CLOCK->LFCLKSRC = 0; //disconnect XL1 AND XL2 FROM LFCLK?
+  NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
+  NRF_CLOCK->TASKS_LFCLKSTART    = 1;
+  while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {}
+
+  stepper_setup();
+  radio_setup();
 
   NRF_GPIO->OUTSET = (1<<pin_nrst); //set nrst/nslp high to enable drv8825
-  NRF_GPIO->OUTSET = (1<<pin_direction); //set nrst/nslp high to enable drv8825
 
   while (true) {
-    //Serial.println("hi there");
-    NRF_GPIO->OUTSET = (1<<pin_step);
-    delay(10);
-    NRF_GPIO->OUTCLR = (1<<pin_step);
-    delay(1);
+    int result = radio_recv(); //wait until recieve
+    parse_command(); //todo: move stepping to non-blocking so can receive commands during moves
   }
 }
 
+void loop() {}
 
 
+// draft for using timer for pwm
 
-void loop() {}
+  //NRF_TIMER1->MODE = (TIMER_MODE_MODE_Timer << TIMER_MODE_MODE_Pos) & TIMER_MODE_MODE_Msk;
+  //NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos) & TIMER_BITMODE_BITMODE_Msk;
+  //NRF_TIMER1->PRESCALER = (7 << TIMER_PRESCALER_PRESCALER_Pos) & TIMER_PRESCALER_PRESCALER_Msk;
+  //NRF_TIMER1->SHORTS = ((TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos) & TIMER_SHORTS_COMPARE0_CLEAR_Msk);
+  //NRF_TIMER1->CC[0] = (1 << 15); //50% duty cycle to test
+
+  //enable PPI channel 0 for compare task setting pin high
+  //NRF_PPI->CHEN = (PPI_CHEN_CH0_Enabled << PPI_CHEN_CH0_Pos) & PPI_CHEN_CH0_Msk;
+  //NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0];
+  //NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];
+  //enable PPI channel 1 for compare overflow setting pin low
+  //NRF_PPI->CHEN = (PPI_CHEN_CH1_Enabled << PPI_CHEN_CH1_Pos) & PPI_CHEN_CH1_Msk;
+  //NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER1->EVENTS_;
+  //NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[1];
+
+  //NRF_TIMER1->TASKS_START = 1;  //start timer
diff --git a/nrf52-stepper/nrf52-drv8825/radio.h b/nrf52-stepper/nrf52-drv8825/radio.h
new file mode 100644
index 0000000..b09208b
--- /dev/null
+++ b/nrf52-stepper/nrf52-drv8825/radio.h
@@ -0,0 +1,114 @@
+#define PACKET_BASE_ADDRESS_LENGTH  (2UL)  //Packet base address length field size in bytes
+#define PACKET_LENGTH 4
+#define REDUNDANCY_COUNT 10 //number of transmissions to ensure delivery... hack.
+static int16_t radio_buffer[PACKET_LENGTH] = {0};
+
+//static int16_t reference_buffer[PACKET_LENGTH] = {0}; //for checking against receipt
+
+
+//
+//RADIO
+//
+void radio_setup(){
+  NRF_RADIO->POWER = RADIO_POWER_POWER_Disabled; //turn off radio to reset registers
+  delay(10);
+  NRF_RADIO->POWER = RADIO_POWER_POWER_Enabled; //turn on radio
+  delay(10);
+
+  NRF_RADIO->TXPOWER   = (RADIO_TXPOWER_TXPOWER_Pos3dBm << RADIO_TXPOWER_TXPOWER_Pos);
+  NRF_RADIO->FREQUENCY = 11UL;  // 2400 + X MHz
+  NRF_RADIO->MODE      = (RADIO_MODE_MODE_Nrf_2Mbit << RADIO_MODE_MODE_Pos);
+
+  NRF_RADIO->PREFIX0 = ((uint32_t)0xC0 << 0); // Prefix byte of address 0
+  NRF_RADIO->BASE0 = 0x01234567UL;  // Base address for prefix 0
+  NRF_RADIO->BASE1 = 0x02345678UL;  // Base address for prefix 0
+  NRF_RADIO->TXADDRESS   = 0x00UL;  // Set device address 0 to use when transmitting
+  //NRF_RADIO->RXADDRESSES = 0x01UL;  // X Enable device address 0 to use to select which addresses to receive  
+  NRF_RADIO->RXADDRESSES = 0x02UL;  //Y Enable device address 1 to use to select which addresses to receive  
+
+  // Packet configuration
+  NRF_RADIO->PCNF0 = (0 << RADIO_PCNF0_S1LEN_Pos) | (0 << RADIO_PCNF0_S0LEN_Pos) | (0 << RADIO_PCNF0_LFLEN_Pos); 
+  NRF_RADIO->PCNF1 = (RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos) |
+                     ((PACKET_LENGTH) << RADIO_PCNF1_STATLEN_Pos) |
+                     (RADIO_PCNF1_ENDIAN_Big       << RADIO_PCNF1_ENDIAN_Pos)  |
+                     (2 << RADIO_PCNF1_BALEN_Pos);
+  NRF_RADIO->CRCCNF = (RADIO_CRCCNF_LEN_Three << RADIO_CRCCNF_LEN_Pos); // Number of checksum bits
+  NRF_RADIO->CRCINIT = 0xFFFFUL; // Initial value
+  NRF_RADIO->CRCPOLY = 0x18D; //x8 + x7 + x3 + x2 + 1 = 110001101 
+  NRF_RADIO->MODECNF0 |= RADIO_MODECNF0_RU_Fast << RADIO_MODECNF0_RU_Pos; //turn on fast ramp up
+  NRF_RADIO->SHORTS = 0; //turn off all shortcuts, for debug
+  NRF_RADIO->PACKETPTR = (uint32_t)&radio_buffer; //set pointer to packet buffer
+  //start HFCLK
+  NRF_CLOCK->TASKS_HFCLKSTART = 1;
+  while(!(NRF_CLOCK->HFCLKSTAT & CLOCK_HFCLKSTAT_STATE_Msk)); //wait for hfclk to start
+  delay(10);
+}
+
+void radio_wait_for_end(){ while(!(NRF_RADIO->EVENTS_END)); NRF_RADIO->EVENTS_END = 0;} //clear end event  
+void radio_wait_for_ready(){ while(!(NRF_RADIO->EVENTS_READY)); NRF_RADIO->EVENTS_READY = 0;} //clear ready event
+void radio_disable(){
+  NRF_RADIO->EVENTS_DISABLED = 0; //clear disabled event
+  NRF_RADIO->TASKS_DISABLE = 1;
+  while(!(NRF_RADIO->EVENTS_DISABLED)); 
+}
+void radio_send(){
+  NRF_RADIO->EVENTS_READY = 0; //clear ready event
+  NRF_RADIO->TASKS_TXEN=1; //trigger tx enable task
+  delayMicroseconds(20);
+  //radio_wait_for_ready(); //only generated when actually switching to tx mode
+  NRF_RADIO->TASKS_START=1;  //start
+  radio_wait_for_end();
+}
+void radio_send_redundant(){
+  for(int i=0; i<REDUNDANCY_COUNT; i++){
+    radio_send();
+  }
+}
+
+int radio_recv(){
+  //return number of packets before CRC match
+  NRF_RADIO->EVENTS_CRCOK = 0; 
+  //NRF_RADIO->EVENTS_CRCERROR = 0; 
+  int i=1;
+  while(true){
+    NRF_RADIO->EVENTS_READY = 0; //clear ready event
+    NRF_RADIO->TASKS_RXEN=1; //trigger rx enable task
+    delayMicroseconds(20);
+    //radio_wait_for_ready(); //only generated when actually switching to rx mode 
+    NRF_RADIO->TASKS_START=1;
+    radio_wait_for_end();
+    if (NRF_RADIO->EVENTS_CRCOK == 1){ break;}
+    i++;
+  }
+  return i;
+}
+
+
+/*
+// start of 3 way handshake implementation
+void copy_buffer_to_reference(){
+  for(int i=0; i++; i<PACKET_LENGTH){
+    reference_buffer[i] = radio_buffer[i];
+  }
+}
+bool buffer_matches_reference(){
+  bool match = true;
+  for(int i=0; i++; i<PACKET_LENGTH){
+    if (reference_buffer[i] != radio_buffer[i]){
+      match = false;
+      break;
+    }
+  }
+  return match;
+}
+void radio_send_with_handshake(){
+  copy_buffer_to_reference();
+  radio_send(); //send packet
+  int crc_match = radio_recv(); //receive ack
+  if crc_match && buffer_matches_reference(){
+    radio_send(); //send ack
+  }
+}
+*/
+
+
-- 
GitLab