From 48ffde059436686ef567506c8e8f5ef4551b94a2 Mon Sep 17 00:00:00 2001 From: Jake <jake.read@cba.mit.edu> Date: Fri, 6 Oct 2017 20:40:17 -0400 Subject: [PATCH] spi module update --- .../spi/nrfer_spi_alive/nrfer_spi_alive.ino | 129 ----------------- modules/spi/nrfer_spi_alive/pins.h | 20 --- modules/spi/spi.ino | 134 ++++++++++++++++++ 3 files changed, 134 insertions(+), 149 deletions(-) delete mode 100644 modules/spi/nrfer_spi_alive/nrfer_spi_alive.ino delete mode 100644 modules/spi/nrfer_spi_alive/pins.h create mode 100644 modules/spi/spi.ino diff --git a/modules/spi/nrfer_spi_alive/nrfer_spi_alive.ino b/modules/spi/nrfer_spi_alive/nrfer_spi_alive.ino deleted file mode 100644 index 31ca6b5..0000000 --- a/modules/spi/nrfer_spi_alive/nrfer_spi_alive.ino +++ /dev/null @@ -1,129 +0,0 @@ -#include <AccelStepper.h> -#include "pins.h" - -AccelStepper stepper(AccelStepper::DRIVER, STEP_PIN, DIR_PIN); - -void setup() { - pinMode(LED_PIN_1, OUTPUT); - pinMode(LED_PIN_2, OUTPUT); - pinMode(LED_PIN_3, OUTPUT); - outclr(LED_PIN_1); - outclr(LED_PIN_2); - outclr(LED_PIN_3); - - stepper.setEnablePin(ENABLE_PIN); - stepper.setPinsInverted(false, false, true); - stepper.setMaxSpeed(10000.0); - stepper.setAcceleration(1000.0); - stepper.enableOutputs(); - stepper.moveTo(5000); - - SPI_Setup(); - - Serial.begin(115200); -} - -uint32_t ticker = 0; -bool cntr = true; - -void loop() { - ticker ++; - - if (stepper.distanceToGo() == 0 ) { - stepper.moveTo(-stepper.currentPosition()); - } - - //stepper.run(); - - if (!(ticker % 25000)) { - SPI_Test(); - if (cntr) { - cntr = false; - outclr(LED_PIN_2); - } else { - cntr = true; - outset(LED_PIN_2); - } - } -} - -#define NRF_SPI_BUFFER_SIZE 4 // 5 8-bit words, making up: -#define NRF_SPI_NUM_BUFFER 1 // one buffer, one 40-bit word - -typedef struct SPIArrayList { - uint8_t buffer[NRF_SPI_BUFFER_SIZE]; -} SPIArrayList_type; - -SPIArrayList_type RX_Buffer[NRF_SPI_NUM_BUFFER]; // 3 words -SPIArrayList_type TX_Buffer[NRF_SPI_NUM_BUFFER]; - -void SPI_Setup() { - /* - NRF52 Datasheet pg 283: must cfg pins for GPIO 1st - CS: Output, value 0 - SCK: Output, value 'same as CONFIG.CPOL' (so dep. on SPI mode) - MOSI: Output, value 0 - MISO: Input - */ - NRF_GPIO->DIRSET = (1 << CS_PIN); - NRF_GPIO->DIRSET = (1 << SCK_PIN); - NRF_GPIO->DIRSET = (1 << MOSI_PIN); - NRF_GPIO->DIRSET = (0 << MISO_PIN); - /* - Enabling SPI, setting pins - CS Pin is not associated with this module, u do u - */ - NRF_SPIM0->ENABLE = SPIM_ENABLE_ENABLE_Enabled; - NRF_SPIM0->PSEL.SCK = SCK_PIN; - NRF_SPIM0->PSEL.MOSI = MOSI_PIN; - NRF_SPIM0->PSEL.MISO = MISO_PIN; - /* - Frequency - */ - NRF_SPIM0->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K250; - /* - Config - */ - NRF_SPIM0->CONFIG = (SPIM_CONFIG_CPOL_Msk << SPIM_CONFIG_CPOL_ActiveHigh) | - (SPIM_CONFIG_CPHA_Msk << SPIM_CONFIG_CPHA_Leading) | - (SPIM_CONFIG_ORDER_Msk << SPIM_CONFIG_ORDER_MsbFirst); - /* - DMA to Send Buffers - */ - NRF_SPIM0->TXD.MAXCNT = NRF_SPI_BUFFER_SIZE * NRF_SPI_NUM_BUFFER; - NRF_SPIM0->TXD.PTR = (uint32_t)&TX_Buffer; - NRF_SPIM0->RXD.MAXCNT = NRF_SPI_BUFFER_SIZE * NRF_SPI_NUM_BUFFER; - NRF_SPIM0->RXD.PTR = (uint32_t)&RX_Buffer; - - //outset(CS_PIN); -} - -void SPI_Test() { - for (int i = 0; i < NRF_SPI_NUM_BUFFER; i++) { - TX_Buffer[i].buffer[0] = 0x6F; // addr. byte - TX_Buffer[i].buffer[1] = 0x00; - TX_Buffer[i].buffer[2] = 0x00; - TX_Buffer[i].buffer[3] = 0x00; - } - - NRF_SPIM0->EVENTS_STARTED = 0; - NRF_SPIM0->EVENTS_END = 0; - outclr(CS_PIN); // go lo - NRF_SPIM0->TASKS_START = 1; - - outset(LED_PIN_3); - while (NRF_SPIM0->EVENTS_STARTED == 0) {} // wait 4 start - outclr(LED_PIN_3); - outset(LED_PIN_1); - while (NRF_SPIM0->EVENTS_END == 0) {} // does the business - outclr(LED_PIN_1); - outset(CS_PIN); -} - -void outclr(uint8_t pin) { - NRF_GPIO->OUTCLR = (1 << pin); -} - -void outset(uint8_t pin) { - NRF_GPIO->OUTSET = (1 << pin); -} diff --git a/modules/spi/nrfer_spi_alive/pins.h b/modules/spi/nrfer_spi_alive/pins.h deleted file mode 100644 index f78d128..0000000 --- a/modules/spi/nrfer_spi_alive/pins.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef PINS_H -#define PINS_H - -#define LED_PIN_1 20 // R -#define LED_PIN_2 11 // G -#define LED_PIN_3 12 // B - -#define STEP_PIN 13 -#define DIR_PIN 18 -#define ENABLE_PIN 3 - -#define DIAG0 7 -#define DIAG1 9 - -#define MOSI_PIN 14 -#define MISO_PIN 10 -#define SCK_PIN 16 -#define CS_PIN 19 - -#endif diff --git a/modules/spi/spi.ino b/modules/spi/spi.ino new file mode 100644 index 0000000..841607f --- /dev/null +++ b/modules/spi/spi.ino @@ -0,0 +1,134 @@ +/* + Pins for SPI +*/ +#define MOSI_PIN 14 +#define MISO_PIN 2 +#define SCK_PIN 16 +#define CS_PIN 19 + +/* + buffers +*/ +#define NUM_WORDS_BUFFER 1 // # of 'words' in the buffer +#define NUM_BYTES_WORD 5 // # of bytes per 'word' + +typedef struct SPIArrayList { + uint8_t buf[NUM_BYTES_WORD]; +} SPIArrayList_type; + +SPIArrayList_type SPI_RX[NUM_WORDS_BUFFER]; +SPIArrayList_type SPI_TX[NUM_WORDS_BUFFER]; + +void setup() { + /* + NRF52 Datasheet pg 283: must cfg pins for GPIO 1st + CS: Output, value 0 + SCK: Output, value 'same as CONFIG.CPOL' (so dep. on SPI mode) + MOSI: Output, value 0 + MISO: Input + FOR REGISTERS: look in (version #s may change) (from windows machine, probably different-but-similar on mac / ubuntu + /yourusername/AppData/Local/Arduino15/packages/adafruit/hardware/nrf52/0.7.5/cores/nRF5/SKD/components/device/nrf52_bitfields.h + and /nrf.h + and /nrf52.h + also available in SDK from Nordic + */ + NRF_GPIO->DIRSET = (1 << CS_PIN); + NRF_GPIO->DIRSET = (1 << SCK_PIN); + NRF_GPIO->DIRSET = (1 << MOSI_PIN); + NRF_GPIO->DIRSET = (0 << MISO_PIN); + NRF_GPIO->PIN_CNF[MISO_PIN] = (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | + (GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos); + /* + Enabling SPI, setting pins + CS Pin is not associated with this module, u do u + */ + NRF_SPIM0->ENABLE = (SPIM_ENABLE_ENABLE_Enabled << SPIM_ENABLE_ENABLE_Pos); + NRF_SPIM0->PSEL.SCK = SCK_PIN; + NRF_SPIM0->PSEL.MOSI = MOSI_PIN; + NRF_SPIM0->PSEL.MISO = MISO_PIN; + /* + Frequency - device & electronics quality dependent. I generally dial this up until it breaks, and then come down by 2/3 + */ + NRF_SPIM0->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M1; // 1MBps + // SPI_FREQUENCY_FREQUENCY_K250 // 250kB/s + // SPI_FREQUENCY_FREQUENCY_K500 // 500kB/s + // SPI_FREQUENCY_FREQUENCY_M1 // 1MB/s + // SPI_FREQUENCY_FREQUENCY_M2 // 2MB/s + /* + Config - device dependent, best to read datasheet carefully + */ + NRF_SPIM0->CONFIG = (SPIM_CONFIG_CPOL_Msk << SPIM_CONFIG_CPOL_ActiveHigh) | // or ActiveLow + (SPIM_CONFIG_CPHA_Msk << SPIM_CONFIG_CPHA_Leading) | // or CPHA_Trailing + (SPIM_CONFIG_ORDER_Msk << SPIM_CONFIG_ORDER_LsbFirst); // or MsbFirst + /* + DMA to Send Buffers + MAXCNT is the # of bytes the SPI module will send + PTR an address to those bytes. see globally defined buffers above + */ + NRF_SPIM0->TXD.MAXCNT = NUM_BYTES_WORD * NUM_WORDS_BUFFER; + NRF_SPIM0->TXD.PTR = (uint32_t)&SPI_TX; + NRF_SPIM0->RXD.MAXCNT = NUM_BYTES_WORD * NUM_WORDS_BUFFER; + NRF_SPIM0->RXD.PTR = (uint32_t)&SPI_RX; + + NRF_GPIO->OUTSET = (1 << CS_PIN); // set line inactive (high) + + Serial.begin(115200); // for testing +} + +uint32_t lastms = 0; +uint32_t period = 1000; + +void loop() { + if((millis() - lastms) > period){ + lastms - millis(); + /* + * setup your buffer, do this however you'd like + */ + SPI_TX[0].buf[0] = 0x00; + SPI_TX[0].buf[1] = 0x01; + SPI_TX[0].buf[2] = 0x02; + SPI_TX[0].buf[3] = 0x03; + SPI_TX[0].buf[4] = 0x04; + /* + * do the business + */ + blockingSpiTransfer(); + /* + * reply is now available in SPI_RX[0].buf[n] + * -> this is set up as an MD array because most spi 'words' are longer than 1 byte, + * so it's useful to have a buffer[x].ofWords[n] + * in the event you are transferring lots of data and want to not-block, + * you can keep filling the buffer[x] and set up events to fire when it's empty, full etc... + */ + Serial.print(SPI_RX[0].buf[0], BIN); // will print 0s and 1s to the line, can also spec HEX (default is ASCII) + Serial.print(" | "); + Serial.print(SPI_RX[0].buf[1], BIN); + Serial.print(" | "); + Serial.print(SPI_RX[0].buf[2], BIN); + Serial.print(" | "); + Serial.print(SPI_RX[0].buf[3], BIN); + Serial.print(" | "); + Serial.print(SPI_RX[0].buf[4], BIN); + Serial.print(" | "); + /* + * also: when reading a register, you normally have to send the 'read from' command twice + * as the device has to have a chance to shift its reply bits into the buffer it uses to reply with. + */ + } +} + + +void blockingSpiTransfer() { + NRF_GPIO->OUTCLR = (1 << CS_PIN); // tells device to start listening (active low) + + NRF_SPIM0->EVENTS_STARTED = 0; // clear these events + NRF_SPIM0->EVENTS_END = 0; + NRF_SPIM0->TASKS_START = 1; // ready go + + // now SPI hardware is pulling from the TX and pushing into the RX buffers + + while (NRF_SPIM0->EVENTS_STARTED == 0) {} // wait 4 start + while (NRF_SPIM0->EVENTS_END == 0) {} // wait 4 spi module to do the business (todo: non blocking event based C++!) + + NRF_GPIO->OUTSET = (1 << CS_PIN); // goodbye +} -- GitLab