Pico-Arduino
PicoHardwareSPI.h
1 #pragma once
2 
3 #include "HardwareSPI.h"
4 #include "pico/stdlib.h"
5 #include "hardware/spi.h"
6 #include "hardware/irq.h"
7 
15 class PicoHardwareSPI : public HardwareSPI {
16  public:
17  PicoHardwareSPI(spi_inst_t *spi){
18  this->spi = spi;
19  }
20 
21  ~PicoHardwareSPI(){
22  end();
23  }
24 
29  virtual void begin() {
30  begin(false, -1,-1,-1,-1);
31  };
32 
42  virtual void begin(bool slave, int pinRx=-1, int pinTx=-1, int pinCS=-1, int pinSCK=-1) {
43  spi_set_slave(spi, slave);
44  setupPins(pinRx, pinTx, pinCS, pinSCK);
45  }
46 
51  virtual void end() {
52  spi_deinit(spi);
53  is_init = false;
54  }
55 
61  virtual void beginTransaction(SPISettings settings) {
62  if (last_settings != settings || !is_init){
63  spi_init (spi, settings.getClockFreq() );
64  is_init = true;
65  SPIMode mode = settings.getDataMode();
66 
67  switch (mode) {
68  case SPI_MODE0:
69  cpol=SPI_CPOL_0;cpha=SPI_CPHA_0;
70  break;
71  case SPI_MODE1:
72  cpol=SPI_CPOL_0;cpha=SPI_CPHA_1;
73  break;
74  case SPI_MODE2:
75  cpol=SPI_CPOL_1;cpha=SPI_CPHA_0;
76  break;
77  case SPI_MODE3:
78  cpol=SPI_CPOL_1;cpha=SPI_CPHA_1;
79  break;
80  }
81 
82  BitOrder order_arduino = settings.getBitOrder();
83  spi_order_t order = order_arduino == LSBFIRST ? SPI_LSB_FIRST : SPI_MSB_FIRST;
84  data_bits = 8;
85  setFormat();
86  }
87 
88  if (using_interrupt_no!=0)
89  irq_set_enabled(using_interrupt_no, false);
90  is_transaction = true;
91  }
92 
97  virtual void endTransaction(void) {
98  is_transaction = false;
99 
100  if (using_interrupt_no!=0)
101  irq_set_enabled(using_interrupt_no, true);
102  }
103 
110  virtual uint8_t transfer(uint8_t data) {
111  uint8_t array[1]={data};
112  transfer(array, 1);
113  return array[0];
114  }
115 
122  virtual uint16_t transfer16(uint16_t data){
123  uint16_t result;
124  spi_write16_read16_blocking(spi, &data, &result, 1);
125  return result;
126  }
127 
135  virtual void transfer(void *array, size_t len) {
136  spi_write_read_blocking(spi, (const uint8_t*) array, (uint8_t*) array, len);
137  }
138 
146  virtual void usingInterrupt(int interruptNumber) {
147  using_interrupt_no = interruptNumber;
148  }
149 
150  virtual void notUsingInterrupt(int interruptNumber) {
151  irq_set_enabled(interruptNumber, true);
152  using_interrupt_no = 0;
153  }
154 
155  virtual void attachInterrupt() {
156  int interrupt = getStandardInterrupt();
157  if(interrupt>0){
158  irq_set_enabled(interrupt, true);
159  }
160  }
161 
162  virtual void detachInterrupt() {
163  int interrupt = getStandardInterrupt();
164  if(interrupt>0){
165  irq_set_enabled(interrupt, false);
166  }
167  }
168 
169  protected:
170  spi_inst_t* spi;
171  bool is_transaction;
172  //transaction info
173  spi_cpol_t cpol;
174  spi_cpha_t cpha;
175  spi_order_t order;
176  uint data_bits;
177  int using_interrupt_no;
178  bool is_init;
179  SPISettings last_settings;
180 
181  // SPI0_IRQ = 18, SPI1_IRQ = 19
182  int getStandardInterrupt(){
183  int interrupt;
184  if (spi == spi0){
185  interrupt = 18;
186  } else if (spi == spi0){
187  interrupt = 19;
188  }
189  return interrupt;
190  }
191 
192  void setFormat(){
193  spi_set_format(spi, data_bits, cpol, cpha, order);
194  }
195 
196  void setupPins(int pinRx=-1, int pinTx=-1, int pinCS=-1, int pinSCK=-1){
197  if (spi == spi0){
198  if (pinRx==-1){
199  pinRx = 16;
200  }
201  if (pinTx==-1){
202  pinTx = 19;
203  }
204  if (pinCS==-1){
205  pinCS = 17;
206  }
207  if (pinSCK==-1){
208  pinSCK = 18;
209  }
210  } else if (spi == spi1){
211  if (pinRx==-1){
212  pinRx = 12;
213  }
214  if (pinTx==-1){
215  pinTx = 11;
216  }
217  if (pinCS==-1){
218  pinCS = 13;
219  }
220  if (pinSCK==-1){
221  pinSCK = 10;
222  }
223 
224  gpio_set_function(pinRx, GPIO_FUNC_SPI);
225  gpio_set_function(pinSCK, GPIO_FUNC_SPI);
226  gpio_set_function(pinTx, GPIO_FUNC_SPI);
227 
228  // Chip select is active-low, so we'll initialise it to a driven-high state
229  gpio_init(pinCS);
230  gpio_set_dir(pinCS, GPIO_OUT);
231  gpio_put(pinCS, 1);
232 
233  // display pin assignments
234  if (Logger.isLogging()) {
235  Logger.info("pinRx is ", toStr(pinRx));
236  Logger.info("pinTx is ", toStr(pinTx));
237  Logger.info("pinSCK is ", toStr(pinSCK));
238  Logger.info("pinCS is ", toStr(pinCS));
239  }
240  } else {
241  Logger.error("Invalid SPI device");
242  }
243 
244  }
245 
246  const char* toStr(int value){
247  static char buffer[10];
248  itoa(value,buffer,10);
249  return (const char*)buffer;
250  }
251 
252 
253 };
Arduino HardwareSPI interface using the Pico API. We use the following default pins spi0: pinRx = 16;...
Definition: PicoHardwareSPI.h:15
virtual void end()
Disables the SPI bus (leaving pin modes unchanged).
Definition: PicoHardwareSPI.h:51
virtual void begin(bool slave, int pinRx=-1, int pinTx=-1, int pinCS=-1, int pinSCK=-1)
Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low,...
Definition: PicoHardwareSPI.h:42
virtual void transfer(void *array, size_t len)
SPI transfer is based on a simultaneous send and receive of len bytes.
Definition: PicoHardwareSPI.h:135
virtual uint8_t transfer(uint8_t data)
SPI transfer is based on a simultaneous send and receive of 1 byte.
Definition: PicoHardwareSPI.h:110
virtual void usingInterrupt(int interruptNumber)
If your program will perform SPI transactions within an interrupt, call this function to register the...
Definition: PicoHardwareSPI.h:146
virtual void beginTransaction(SPISettings settings)
Initializes the SPI bus using the defined SPISettings.
Definition: PicoHardwareSPI.h:61
virtual void begin()
Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low,...
Definition: PicoHardwareSPI.h:29
virtual uint16_t transfer16(uint16_t data)
SPI transfer is based on a simultaneous send and receive of 2 bytes.
Definition: PicoHardwareSPI.h:122
virtual void endTransaction(void)
Stop using the SPI bus. Normally this is called after de-asserting the chip select,...
Definition: PicoHardwareSPI.h:97
Definition: HardwareSPI.h:105
Definition: HardwareSPI.h:37