Pico-Arduino
PicoHardwareSPI.h
1 #pragma once
2 
3 #include "pins_arduino.h"
4 #include "HardwareSPI.h"
5 #include "pico/stdlib.h"
6 #include "hardware/spi.h"
7 #include "hardware/irq.h"
8 
19 class PicoHardwareSPI : public HardwareSPI {
20  public:
21  PicoHardwareSPI(spi_inst_t *spi){
22  this->spi = spi;
23  }
24 
25  ~PicoHardwareSPI(){
26  end();
27  }
28 
33  virtual void begin() {
34  begin(false, -1,-1,-1,-1);
35  };
36 
46  virtual void begin(bool slave, int pinRx=-1, int pinTx=-1, int pinCS=-1, int pinSCK=-1) {
47  Logger.info("begin");
48  is_slave = slave;
49  setupPins(pinRx, pinTx, pinCS, pinSCK);
50  }
51 
56  virtual void end() {
57  Logger.info("end");
58  spi_deinit(spi);
59  is_init = false;
60  }
61 
67  virtual void beginTransaction(SPISettings settings) {
68  Logger.debug("beginTransaction");
69  is_transaction = true;
70 
71  // initialize on first transction
72  if (!is_init){
73  Logger.info("spi_init");
74  spi_init (spi, settings.getClockFreq() );
75 
76  // Configure the SPI for master- or slave-mode operation. By default, spi_init() sets master-mode.
77  if (is_slave){
78  spi_set_slave(spi, is_slave);
79  }
80 
81  is_init = true;
82  }
83 
84  // set baud rate and format on change of settings
85  if (last_settings != settings){
86  SPIMode mode = settings.getDataMode();
87  Logger.info("spi_set_baudrate", Logger.toStr(settings.getClockFreq()));
88  spi_set_baudrate(spi, settings.getClockFreq());
89 
90  switch (mode) {
91  case SPI_MODE0:
92  Logger.info("mode", "MODE0");
93  cpol=SPI_CPOL_0;cpha=SPI_CPHA_0;
94  break;
95  case SPI_MODE1:
96  Logger.info("mode", "MODE0");
97  cpol=SPI_CPOL_0;cpha=SPI_CPHA_1;
98  break;
99  case SPI_MODE2:
100  Logger.info("mode", "MODE0");
101  cpol=SPI_CPOL_1;cpha=SPI_CPHA_0;
102  break;
103  case SPI_MODE3:
104  Logger.info("mode", "MODE0");
105  cpol=SPI_CPOL_1;cpha=SPI_CPHA_1;
106  break;
107  default:
108  Logger.error("Invalid Mode");
109  break;
110 
111  }
112 
113  BitOrder order_arduino = settings.getBitOrder();
114  order = (order_arduino == LSBFIRST ) ? SPI_LSB_FIRST : SPI_MSB_FIRST;
115  data_bits = 0;
116  last_settings = settings;
117  }
118 
119  if (using_interrupt_no!=0) {
120  Logger.info("irq_set_enabled false");
121  irq_set_enabled(using_interrupt_no, false);
122  }
123  }
124 
129  virtual void endTransaction(void) {
130  Logger.debug("endTransaction");
131  is_transaction = false;
132 
133  if (using_interrupt_no!=0) {
134  Logger.info("irq_set_enabled true");
135  irq_set_enabled(using_interrupt_no, true);
136  }
137  }
138 
145  virtual uint8_t transfer(uint8_t data) {
146  Logger.debug("transfer");
147  setDataWidth(8);
148  uint8_t array[1]={data};
149  uint8_t arrayResult[1] = {0};
150  spi_write_read_blocking(spi, array, arrayResult, 1);
151  return arrayResult[0];
152  }
153 
160  virtual uint16_t transfer16(uint16_t data){
161  Logger.debug("transfer16");
162  setDataWidth(16);
163  uint16_t result;
164  spi_write16_read16_blocking(spi, &data, &result, 1);
165  return result;
166  }
167 
175  virtual void transfer(void *array, size_t len) {
176  Logger.debug("transfer (array)");
177  setDataWidth(8);
178  spi_write_read_blocking(spi, (const uint8_t*) array, (uint8_t*) array, len);
179  }
180 
188  virtual void usingInterrupt(int interruptNumber) {
189  Logger.info("usingInterrupt", Logger.toStr(interruptNumber));
190  using_interrupt_no = interruptNumber;
191  }
192 
194  virtual void notUsingInterrupt(int interruptNumber) {
195  Logger.info("notUsingInterrupt",Logger.toStr(interruptNumber));
196  irq_set_enabled(interruptNumber, true);
197  using_interrupt_no = 0;
198  }
199 
201  virtual void attachInterrupt() {
202  Logger.info("attachInterrupt");
203  int interrupt = getStandardInterrupt();
204  if(interrupt>0){
205  irq_set_enabled(interrupt, true);
206  }
207  }
208 
210  virtual void detachInterrupt() {
211  Logger.info("detachInterrupt");
212  int interrupt = getStandardInterrupt();
213  if(interrupt>0){
214  irq_set_enabled(interrupt, false);
215  }
216  }
217 
218  protected:
219  SPISettings last_settings; // Arduino SPI settings
220  spi_inst_t* spi;
221  spi_cpol_t cpol;
222  spi_cpha_t cpha;
223  spi_order_t order;
224  uint data_bits;
225  int using_interrupt_no;
226  bool is_init = false;
227  bool is_slave;
228  bool is_transaction;
229 
230  // SPI0_IRQ = 18, SPI1_IRQ = 19
231  int getStandardInterrupt(){
232  int interrupt;
233  if (spi == spi0){
234  interrupt = 18;
235  } else if (spi == spi0){
236  interrupt = 19;
237  }
238  return interrupt;
239  }
240 
241  // adjust data bits
242  void setDataWidth(int bits){
243  if (data_bits != bits){
244  data_bits = bits;
245  setFormat();
246  }
247  }
248 
249  void setFormat(){
250  Logger.info("spi_set_format");
251  spi_set_format(spi, data_bits, cpol, cpha, order);
252  }
253 
254  void setupPins(int pinRx=-1, int pinTx=-1, int pinCS=-1, int pinSCK=-1){
255  if (spi == spi0){
256  Logger.info("setupPins for spi0");
257  if (pinRx==-1){
258  pinRx = SPI_RX;
259  }
260  if (pinTx==-1){
261  pinTx = SPI_TX;
262  }
263  if (pinCS==-1){
264  pinCS = SPI_CS;
265  }
266  if (pinSCK==-1){
267  pinSCK = SPI_SCK;
268  }
269  } else if (spi == spi1){
270  Logger.info("setupPins for spi1");
271  if (pinRx==-1){
272  pinRx = SPI1_RX;
273  }
274  if (pinTx==-1){
275  pinTx = SPI1_TX;
276  }
277  if (pinCS==-1){
278  pinCS = SPI1_CS;
279  }
280  if (pinSCK==-1){
281  pinSCK = SPI1_SCK;
282  }
283 
284  } else {
285  Logger.error("Invalid SPI device");
286  }
287 
288  gpio_set_function(pinRx, GPIO_FUNC_SPI);
289  gpio_set_function(pinSCK, GPIO_FUNC_SPI);
290  gpio_set_function(pinTx, GPIO_FUNC_SPI);
291 
292  // Chip select is active-low, so we'll initialise it to a driven-high state
293  gpio_init(pinCS);
294  gpio_set_dir(pinCS, GPIO_OUT);
295  gpio_put(pinCS, 1);
296 
297  // display pin assignments
298  if (Logger.isLogging()) {
299  Logger.info("pinRx is ", Logger.toStr(pinRx));
300  Logger.info("pinTx is ", Logger.toStr(pinTx));
301  Logger.info("pinSCK is ", Logger.toStr(pinSCK));
302  Logger.info("pinCS is ", Logger.toStr(pinCS));
303  }
304 
305  }
306 
307 
308 
309 };
Arduino HardwareSPI interface using the Pico API. We use the following default pins spi0: pinRx = 16;...
Definition: PicoHardwareSPI.h:19
virtual void end()
Disables the SPI bus (leaving pin modes unchanged).
Definition: PicoHardwareSPI.h:56
virtual void attachInterrupt()
Enable the SPI interrupt: SPI0_IRQ = 18, SPI1_IRQ = 19.
Definition: PicoHardwareSPI.h:201
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:46
virtual void transfer(void *array, size_t len)
SPI transfer is based on a simultaneous send and receive of len bytes.
Definition: PicoHardwareSPI.h:175
virtual uint8_t transfer(uint8_t data)
SPI transfer is based on a simultaneous send and receive of 1 byte.
Definition: PicoHardwareSPI.h:145
virtual void detachInterrupt()
Turns off the given interrupt: SPI0_IRQ = 18, SPI1_IRQ = 19.
Definition: PicoHardwareSPI.h:210
virtual void usingInterrupt(int interruptNumber)
If your program will perform SPI transactions within an interrupt, call this function to register the...
Definition: PicoHardwareSPI.h:188
virtual void beginTransaction(SPISettings settings)
Initializes the SPI bus using the defined SPISettings.
Definition: PicoHardwareSPI.h:67
virtual void notUsingInterrupt(int interruptNumber)
If your program will perform SPI transactions within an interrupt, call this function to de-register ...
Definition: PicoHardwareSPI.h:194
virtual void begin()
Initializes the SPI bus by setting SCK, MOSI, and SS to outputs, pulling SCK and MOSI low,...
Definition: PicoHardwareSPI.h:33
virtual uint16_t transfer16(uint16_t data)
SPI transfer is based on a simultaneous send and receive of 2 bytes.
Definition: PicoHardwareSPI.h:160
virtual void endTransaction(void)
Stop using the SPI bus. Normally this is called after de-asserting the chip select,...
Definition: PicoHardwareSPI.h:129
Definition: HardwareSPI.h:105
Definition: HardwareSPI.h:37