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