Timer and interrupts for multiple SPI using arduino nano 33 BLE Sense REV2 Board

Hello,
I am programming by arduino nano 33 BLE sense REV2 board, for two SPI to communicate with two AFEs. For driving two AFEs, I am trying to generate two 8MHz clock for each AFE, but I am getting one clock of 8MHz and the other is just 4kHz.
Moreover, I am trying to use the interrupts for SPIs but it just work for one AFE and also on 'LOW' not on 'FALLING'.
I looked for solution on arduino forums and think that it is due to timer and external interrupts may be, I am not sure. does anyone have a solution for this?

Thanks in advance.

Here is the sketch:

#include <SPI.h>
#include <stdio.h>
#include <stdlib.h>
#include <nrf.h>
#include <NRF52_MBED_TimerInterrupt.h> // TimerInterrupt_Generic library

NRF52_MBED_Timer ITimer; // Timer object


#define CLOCK_OUTPUT_PIN1 4 // P0.04 (8 MHz clock on pin A0)
#define CLOCK_OUTPUT_PIN2 30 // P0.30 (8 MHz clock on pin A2)


#define SPI_CLOCK 4000000    // 4 MHz SPI clock
#define SPI_MODE SPI_MODE0   // SPI mode
#define SPI_ORDER MSBFIRST   // Most Significant Bit First

#define true 1
#define false 0

// Pin definitions for AFE1 (SPI0)
#define MOSI_1 11
#define MISO_1 12
#define SCK_1 13
#define SS_1 10
#define PDNZ_1 9       // Custom PDNZ pin
#define ADC_RDY_1 8    // Custom ADC_RDY pin

// Pin definitions for AFE2 (SPI1)
#define SS_2 7
#define PDNZ_2 6       // Custom PDNZ pin
#define ADC_RDY_2 5    // ADC_RDY pin for AFE2

volatile bool readDataFlag1 = false; // Flag for AFE1
volatile bool readDataFlag2 = false; // Flag for AFE2

void AFE_Set_Register(byte csPin, byte thisRegister, unsigned long data);



void setup() {
  Serial.begin(9600);


  // Configure GPIO pins for clock outputs
  NRF_P0->PIN_CNF[CLOCK_OUTPUT_PIN1] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) |
                                       (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) |
                                       (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                       (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                       (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);

  NRF_P0->PIN_CNF[CLOCK_OUTPUT_PIN2] = (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos) |
                                       (GPIO_PIN_CNF_INPUT_Disconnect << GPIO_PIN_CNF_INPUT_Pos) |
                                       (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
                                       (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
                                       (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);


  // Configure TIMER4 for 8 MHz clock on CLOCK_OUTPUT_PIN1
  NRF_TIMER4->MODE = TIMER_MODE_MODE_Timer; // Set as Timer
  NRF_TIMER4->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos; // 16-bit Timer
  NRF_TIMER4->PRESCALER = 0; // Prescaler 0 -> Full Speed (16 MHz base clock)
  NRF_TIMER4->CC[0] = 1; // Toggle every 1 cycle (16 MHz / 2 = 8 MHz)
  NRF_TIMER4->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;


  // Configure GPIOTE for toggling CLOCK_OUTPUT_PIN1
  NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
                          (CLOCK_OUTPUT_PIN1 << GPIOTE_CONFIG_PSEL_Pos) |
                          (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);


  // Configure TIMER3 for 8 MHz clock on CLOCK_OUTPUT_PIN2
  NRF_TIMER3->MODE = TIMER_MODE_MODE_Timer; // Set as Timer
  NRF_TIMER3->BITMODE = TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos; // 16-bit Timer
  NRF_TIMER3->PRESCALER = 0; // Prescaler 0 -> Full Speed (16 MHz base clock)
  NRF_TIMER3->CC[0] = 1; // Toggle every 1 cycle (16 MHz / 2 = 8 MHz)
  NRF_TIMER3->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;


  // Configure GPIOTE for toggling CLOCK_OUTPUT_PIN2
  NRF_GPIOTE->CONFIG[1] = (GPIOTE_CONFIG_MODE_Task << GPIOTE_CONFIG_MODE_Pos) |
                          (CLOCK_OUTPUT_PIN2 << GPIOTE_CONFIG_PSEL_Pos) |
                          (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos);


  // Configure PPI to connect TIMER4 to CLOCK_OUTPUT_PIN1
  NRF_PPI->CH[0].EEP = (uint32_t)&NRF_TIMER4->EVENTS_COMPARE[0];
  NRF_PPI->CH[0].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[0];


  // Configure PPI to connect TIMER3 to CLOCK_OUTPUT_PIN2
  NRF_PPI->CH[1].EEP = (uint32_t)&NRF_TIMER3->EVENTS_COMPARE[0];
  NRF_PPI->CH[1].TEP = (uint32_t)&NRF_GPIOTE->TASKS_OUT[1];


  // Start TIMER4 for CLOCK_OUTPUT_PIN1
  NRF_TIMER4->TASKS_CLEAR = 1; // Clear Timer 4
  NRF_TIMER4->TASKS_START = 1; // Start Timer 4


  // Start TIMER3 for CLOCK_OUTPUT_PIN2
  NRF_TIMER3->TASKS_CLEAR = 1; // Clear Timer 3
  NRF_TIMER3->TASKS_START = 1; // Start Timer 3

  // Enable PPI channels after timers start

  NRF_PPI->CHENSET = (1 << 0) | (1 << 1); // Enable both PPI channels



  // Initialize pins for AFE1
  pinMode(SS_1, OUTPUT);
  digitalWrite(SS_1, HIGH);
  pinMode(PDNZ_1, OUTPUT);
  digitalWrite(PDNZ_1, HIGH);
  pinMode(ADC_RDY_1, INPUT);

  // Initialize pins for AFE2
  pinMode(SS_2, OUTPUT);
  digitalWrite(SS_2, HIGH);
  pinMode(PDNZ_2, OUTPUT);
  digitalWrite(PDNZ_2, HIGH);
  pinMode(ADC_RDY_2, INPUT);

  // Initialize SPI
  SPI.begin();
  SPI.beginTransaction(SPISettings(SPI_CLOCK, SPI_ORDER, SPI_MODE));

  // Initialize AFE1 and AFE2
  initializeAFE_1();
  initializeAFE_2();

  // Start Timer Interrupt
  if (ITimer.attachInterruptInterval(2000, timerISR)) { // 2000 microseconds = 2ms
    Serial.println("Timer started successfully!");
  } 
  else {
    Serial.println("Failed to start timer!");
  }

  AFE_Set_READABLE(SS_1);
  AFE_Set_READABLE(SS_2);

}


void loop() {
  if (readDataFlag1) {
    readDataFlag1 = false; // Reset the flag
    uint32_t receivedVal1 = AFE_Read_Register(SS_1, 42); // Read GREEN_LED data from AFE1
    //Serial.print("AFE1 GREEN_LED Data: ");
    Serial.print(receivedVal1);
  }

  if (readDataFlag2) {
    readDataFlag2 = false; // Reset the flag
    uint32_t receivedVal2 = AFE_Read_Register(SS_2, 42); // Read GREEN_LED data from AFE2
    Serial.print("\t");
    Serial.print(receivedVal2);
    Serial.print("\n");
  }
}


void initializeAFE_1() {
  AFE_Set_Register(SS_1, 0, 8);     // Control 0 Reset 
  AFE_Set_Register(SS_1, 1, 6050);  // LED2STC
  AFE_Set_Register(SS_1, 2, 7998);  // LED2ENDC
  AFE_Set_Register(SS_1, 3, 6000);  // LED2LEDSTC
  AFE_Set_Register(SS_1, 4, 7999);  // LED2LEDENDC
  AFE_Set_Register(SS_1, 5, 50);    // ALED2STC
  AFE_Set_Register(SS_1, 6, 1998);  // ALED2ENDC
  AFE_Set_Register(SS_1, 7, 2050);  // LED1STC
  AFE_Set_Register(SS_1, 8, 3998);  // LED1ENDC
  AFE_Set_Register(SS_1, 9, 2000);  // LED1LEDSTC
  AFE_Set_Register(SS_1, 10, 3999); // LED1LEDENDC
  AFE_Set_Register(SS_1, 11, 4050); // ALED1STC
  AFE_Set_Register(SS_1, 12, 5998); // ALED1ENDC
  AFE_Set_Register(SS_1, 13, 4);    // LED2CONVST
  AFE_Set_Register(SS_1, 14, 1999); // LED2CONVEND
  AFE_Set_Register(SS_1, 15, 2004); // ALED2CONVST
  AFE_Set_Register(SS_1, 16, 3999); // ALED2CONVEND
  AFE_Set_Register(SS_1, 17, 4004); // LED1CONVST
  AFE_Set_Register(SS_1, 18, 5999); // LED1CONVEND
  AFE_Set_Register(SS_1, 19, 6004); // ALED1CONVST
  AFE_Set_Register(SS_1, 20, 7999); // ALED1CONVEND

  AFE_Set_Register(SS_1, 21, 0);    // ADCRSTSTXT0
  AFE_Set_Register(SS_1, 22, 3);    // ADCRSTENDCT0
  AFE_Set_Register(SS_1, 23, 2000); // ADCRSTSTCT1
  AFE_Set_Register(SS_1, 24, 2003); // ADCRSTENDCT1
  AFE_Set_Register(SS_1, 25, 4000); // ADCRSTSTCT2
  AFE_Set_Register(SS_1, 26, 4003); // ADCRSTENDCT2
  AFE_Set_Register(SS_1, 27, 6000); // ADCRSTSTCT3
  AFE_Set_Register(SS_1, 28, 6003); // ADCRSTENDCT3

  AFE_Set_Register(SS_1, 29, 7999);   // PRPCOUNT
  AFE_Set_Register(SS_1, 30, 0x107);  // CONTROL1
  AFE_Set_Register(SS_1, 32, 0x08002); // TIA_GAIN-----IR
  AFE_Set_Register(SS_1, 33, 0x24402); // TIA_AMB_GAIN------GREEN/RED
  AFE_Set_Register(SS_1, 34, 0x10014); // LEDCNTRL
  AFE_Set_Register(SS_1, 35, 0x40000); // CONTROL2
  AFE_Set_Register(SS_1, 49, 0x08000); // CONTROL3

  digitalWrite(SS_1, HIGH);
}

void initializeAFE_2() {
  AFE_Set_Register(SS_2, 0, 8);     // Control 0 Reset 
  AFE_Set_Register(SS_2, 1, 6050);  // LED2STC
  AFE_Set_Register(SS_2, 2, 7998);  // LED2ENDC
  AFE_Set_Register(SS_2, 3, 6000);  // LED2LEDSTC
  AFE_Set_Register(SS_2, 4, 7999);  // LED2LEDENDC
  AFE_Set_Register(SS_2, 5, 50);    // ALED2STC
  AFE_Set_Register(SS_2, 6, 1998);  // ALED2ENDC
  AFE_Set_Register(SS_2, 7, 2050);  // LED1STC
  AFE_Set_Register(SS_2, 8, 3998);  // LED1ENDC
  AFE_Set_Register(SS_2, 9, 2000);  // LED1LEDSTC
  AFE_Set_Register(SS_2, 10, 3999); // LED1LEDENDC
  AFE_Set_Register(SS_2, 11, 4050); // ALED1STC
  AFE_Set_Register(SS_2, 12, 5998); // ALED1ENDC
  AFE_Set_Register(SS_2, 13, 4);    // LED2CONVST
  AFE_Set_Register(SS_2, 14, 1999); // LED2CONVEND
  AFE_Set_Register(SS_2, 15, 2004); // ALED2CONVST
  AFE_Set_Register(SS_2, 16, 3999); // ALED2CONVEND
  AFE_Set_Register(SS_2, 17, 4004); // LED1CONVST
  AFE_Set_Register(SS_2, 18, 5999); // LED1CONVEND
  AFE_Set_Register(SS_2, 19, 6004); // ALED1CONVST
  AFE_Set_Register(SS_2, 20, 7999); // ALED1CONVEND

  AFE_Set_Register(SS_2, 21, 0);    // ADCRSTSTXT0
  AFE_Set_Register(SS_2, 22, 3);    // ADCRSTENDCT0
  AFE_Set_Register(SS_2, 23, 2000); // ADCRSTSTCT1
  AFE_Set_Register(SS_2, 24, 2003); // ADCRSTENDCT1
  AFE_Set_Register(SS_2, 25, 4000); // ADCRSTSTCT2
  AFE_Set_Register(SS_2, 26, 4003); // ADCRSTENDCT2
  AFE_Set_Register(SS_2, 27, 6000); // ADCRSTSTCT3
  AFE_Set_Register(SS_2, 28, 6003); // ADCRSTENDCT3

  AFE_Set_Register(SS_2, 29, 7999);   // PRPCOUNT
  AFE_Set_Register(SS_2, 30, 0x107);  // CONTROL1
  AFE_Set_Register(SS_2, 32, 0x08002); // TIA_GAIN-----IR
  AFE_Set_Register(SS_2, 33, 0x24402); // TIA_AMB_GAIN------GREEN/RED
  AFE_Set_Register(SS_2, 34, 0x10014); // LEDCNTRL
  AFE_Set_Register(SS_2, 35, 0x40000); // CONTROL2
  AFE_Set_Register(SS_2, 49, 0x08000); // CONTROL3

  digitalWrite(SS_2, HIGH);
}

void timerISR() {
  // Check ADC_RDY pins and set flags accordingly
  if (digitalRead(ADC_RDY_1) == FALLING) {
    readDataFlag1 = true;
  }
  if (digitalRead(ADC_RDY_2) == FALLING) {
    readDataFlag2 = true;
  }
}

void AFE_Set_Register(byte csPin, byte thisRegister, unsigned long data) {
  digitalWrite(csPin, LOW);
  SPI.transfer(thisRegister);
  SPI.transfer((data >> 16) & 0xFF);
  SPI.transfer((data >> 8) & 0xFF);
  SPI.transfer(data & 0xFF);
  digitalWrite(csPin, HIGH);
}

unsigned long AFE_Read_Register(byte csPin, byte addrToRead) {
  unsigned long result = 0;
  digitalWrite(csPin, LOW);
  SPI.transfer(addrToRead);
  result |= (SPI.transfer(0x00) << 16);
  result |= (SPI.transfer(0x00) << 8);
  result |= SPI.transfer(0x00);
  digitalWrite(csPin, HIGH);
  return result;
}

void AFE_Set_READABLE(byte csPin) {
  byte toWrite[3] = {0x00, 0x00, 0x01}; // Data to write to CONTROL0 register
  writeAFERegister(csPin, 0x00, toWrite);
}

void writeAFERegister(byte cs, byte thisRegister, byte AFEValue[]) {
digitalWrite(SS, LOW);
  byte addrToSend = thisRegister;
  SPI.transfer(addrToSend);
  SPI.transfer(AFEValue[0]);
  SPI.transfer(AFEValue[1]);
  SPI.transfer(AFEValue[2]);
  //delayMicroseconds(1);
  digitalWrite(SS, HIGH);
}

I have been searching for days for the syntax.

Where did you find the syntax?

Sorry for the bother.

Mike

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.