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