MySensors Library & Examples  2.3.2
SPIBCM.h
1 /*
2  * The MySensors Arduino library handles the wireless radio link and protocol
3  * between your home built sensors/actuators and HA controller of choice.
4  * The sensors forms a self healing radio network with optional repeaters. Each
5  * repeater and gateway builds a routing tables in EEPROM which keeps track of the
6  * network topology allowing messages to be routed to nodes.
7  *
8  * Created by Henrik Ekblad <[email protected]>
9  * Copyright (C) 2013-2019 Sensnology AB
10  * Full contributor list: https://github.com/mysensors/MySensors/graphs/contributors
11  *
12  * Documentation: http://www.mysensors.org
13  * Support Forum: http://forum.mysensors.org
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * version 2 as published by the Free Software Foundation.
18  *
19  * Based on TMRh20 RF24 library, Copyright (c) 2015 Charles-Henri Hallard <[email protected]>
20  */
21 
22 #ifndef SPIBCM_h
23 #define SPIBCM_h
24 
25 #include <stdio.h>
26 #include "bcm2835.h"
27 #include "BCM.h"
28 
29 #define SPI_HAS_TRANSACTION
30 
31 #define SPI_CLOCK_BASE 256000000
32 
33 // SPI Clock divider
34 #define SPI_CLOCK_DIV1 BCM2835_SPI_CLOCK_DIVIDER_1
35 #define SPI_CLOCK_DIV2 BCM2835_SPI_CLOCK_DIVIDER_2
36 #define SPI_CLOCK_DIV4 BCM2835_SPI_CLOCK_DIVIDER_4
37 #define SPI_CLOCK_DIV8 BCM2835_SPI_CLOCK_DIVIDER_8
38 #define SPI_CLOCK_DIV16 BCM2835_SPI_CLOCK_DIVIDER_16
39 #define SPI_CLOCK_DIV32 BCM2835_SPI_CLOCK_DIVIDER_32
40 #define SPI_CLOCK_DIV64 BCM2835_SPI_CLOCK_DIVIDER_64
41 #define SPI_CLOCK_DIV128 BCM2835_SPI_CLOCK_DIVIDER_128
42 #define SPI_CLOCK_DIV256 BCM2835_SPI_CLOCK_DIVIDER_256
43 #define SPI_CLOCK_DIV512 BCM2835_SPI_CLOCK_DIVIDER_512
44 #define SPI_CLOCK_DIV1024 BCM2835_SPI_CLOCK_DIVIDER_1024
45 #define SPI_CLOCK_DIV2048 BCM2835_SPI_CLOCK_DIVIDER_2048
46 #define SPI_CLOCK_DIV4096 BCM2835_SPI_CLOCK_DIVIDER_4096
47 #define SPI_CLOCK_DIV8192 BCM2835_SPI_CLOCK_DIVIDER_8192
48 #define SPI_CLOCK_DIV16384 BCM2835_SPI_CLOCK_DIVIDER_16384
49 #define SPI_CLOCK_DIV32768 BCM2835_SPI_CLOCK_DIVIDER_32768
50 #define SPI_CLOCK_DIV65536 BCM2835_SPI_CLOCK_DIVIDER_65536
51 
52 // SPI Data mode
53 #define SPI_MODE0 BCM2835_SPI_MODE0
54 #define SPI_MODE1 BCM2835_SPI_MODE1
55 #define SPI_MODE2 BCM2835_SPI_MODE2
56 #define SPI_MODE3 BCM2835_SPI_MODE3
57 
58 #define LSBFIRST BCM2835_SPI_BIT_ORDER_LSBFIRST
59 #define MSBFIRST BCM2835_SPI_BIT_ORDER_MSBFIRST
60 
61 const uint8_t SS = 24;
62 const uint8_t MOSI = 19;
63 const uint8_t MISO = 21;
64 const uint8_t SCK = 23;
65 
70 {
71 
72 public:
79  {
80  init(SPI_CLOCK_DIV32, MSBFIRST, SPI_MODE0);
81  }
89  SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
90  {
91  uint16_t divider;
92 
93  if (clock >= SPI_CLOCK_BASE) {
94  divider = SPI_CLOCK_DIV1;
95  } else if (clock >= SPI_CLOCK_BASE / 2) {
96  divider = SPI_CLOCK_DIV2;
97  } else if (clock >= SPI_CLOCK_BASE / 4) {
98  divider = SPI_CLOCK_DIV4;
99  } else if (clock >= SPI_CLOCK_BASE / 8) {
100  divider = SPI_CLOCK_DIV8;
101  } else if (clock >= SPI_CLOCK_BASE / 16) {
102  divider = SPI_CLOCK_DIV16;
103  } else if (clock >= SPI_CLOCK_BASE / 32) {
104  divider = SPI_CLOCK_DIV32;
105  } else if (clock >= SPI_CLOCK_BASE / 64) {
106  divider = SPI_CLOCK_DIV64;
107  } else if (clock >= SPI_CLOCK_BASE / 128) {
108  divider = SPI_CLOCK_DIV128;
109  } else if (clock >= SPI_CLOCK_BASE / 256) {
110  divider = SPI_CLOCK_DIV256;
111  } else if (clock >= SPI_CLOCK_BASE / 512) {
112  divider = SPI_CLOCK_DIV512;
113  } else if (clock >= SPI_CLOCK_BASE / 1024) {
114  divider = SPI_CLOCK_DIV1024;
115  } else if (clock >= SPI_CLOCK_BASE / 2048) {
116  divider = SPI_CLOCK_DIV2048;
117  } else if (clock >= SPI_CLOCK_BASE / 4096) {
118  divider = SPI_CLOCK_DIV4096;
119  } else if (clock >= SPI_CLOCK_BASE / 8192) {
120  divider = SPI_CLOCK_DIV8192;
121  } else if (clock >= SPI_CLOCK_BASE / 16384) {
122  divider = SPI_CLOCK_DIV16384;
123  } else if (clock >= SPI_CLOCK_BASE / 32768) {
124  divider = SPI_CLOCK_DIV32768;
125  } else if (clock >= SPI_CLOCK_BASE / 65536) {
126  divider = SPI_CLOCK_DIV65536;
127  } else {
128  // Default to 8Mhz
129  divider = SPI_CLOCK_DIV32;
130  }
131 
132  init(divider, bitOrder, dataMode);
133  }
134 
135  uint16_t cdiv;
136  uint8_t border;
137  uint8_t dmode;
138 
139 private:
147  void init(uint16_t divider, uint8_t bitOrder, uint8_t dataMode)
148  {
149  cdiv = divider;
150  border = bitOrder;
151  dmode = dataMode;
152  }
153 
154  friend class SPIBCMClass;
155 };
156 
161 {
162 
163 public:
170  inline static uint8_t transfer(uint8_t data);
178  inline static void transfernb(char* tbuf, char* rbuf, uint32_t len);
185  inline static void transfern(char* buf, uint32_t len);
189  static void begin();
193  static void end();
199  static void setBitOrder(uint8_t bit_order);
205  static void setDataMode(uint8_t data_mode);
211  static void setClockDivider(uint16_t divider);
217  static void chipSelect(int csn_pin);
223  static void beginTransaction(SPISettings settings);
227  static void endTransaction();
233  static void usingInterrupt(uint8_t interruptNumber);
239  static void notUsingInterrupt(uint8_t interruptNumber);
240 
241 private:
242  static uint8_t initialized;
243 };
244 
245 uint8_t SPIBCMClass::transfer(uint8_t data)
246 {
247  return bcm2835_spi_transfer(data);
248 }
249 
250 void SPIBCMClass::transfernb(char* tbuf, char* rbuf, uint32_t len)
251 {
252  bcm2835_spi_transfernb( tbuf, rbuf, len);
253 }
254 
255 void SPIBCMClass::transfern(char* buf, uint32_t len)
256 {
257  transfernb(buf, buf, len);
258 }
259 
260 extern SPIBCMClass SPIBCM;
261 
262 #endif
SPIBCMClass::setClockDivider
static void setClockDivider(uint16_t divider)
Sets the SPI clock divider and therefore the SPI clock speed.
bcm2835_spi_transfernb
void bcm2835_spi_transfernb(char *tbuf, char *rbuf, uint32_t len)
data
char data[MAX_PAYLOAD_SIZE+1]
Buffer for raw payload data.
Definition: MyMessage.h:653
SPISettings::clock
uint32_t clock
SPI clock.
Definition: SPIDEV.h:88
SPIBCMClass::beginTransaction
static void beginTransaction(SPISettings settings)
Start SPI transaction.
bcm2835_spi_transfer
uint8_t bcm2835_spi_transfer(uint8_t value)
SPIBCMClass::transfern
static void transfern(char *buf, uint32_t len)
Send and receive a number of bytes.
Definition: SPIBCM.h:255
SPISettings::SPISettings
SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
SPISettings constructor.
Definition: SPIBCM.h:89
SPISettings
Definition: SPIBCM.h:69
SPIBCMClass::endTransaction
static void endTransaction()
End SPI transaction.
SPISettings::border
uint8_t border
SPI bit order.
Definition: SPIBCM.h:136
SPIBCMClass::chipSelect
static void chipSelect(int csn_pin)
Sets the chip select pin.
SPIBCMClass::transfernb
static void transfernb(char *tbuf, char *rbuf, uint32_t len)
Send and receive a number of bytes.
Definition: SPIBCM.h:250
SPIBCMClass::transfer
static uint8_t transfer(uint8_t data)
Send and receive a byte.
Definition: SPIBCM.h:245
SPIBCMClass::setBitOrder
static void setBitOrder(uint8_t bit_order)
Sets the SPI bit order.
SPIBCMClass
Definition: SPIBCM.h:160
SPIBCMClass::notUsingInterrupt
static void notUsingInterrupt(uint8_t interruptNumber)
Not implemented.
SPIBCMClass::setDataMode
static void setDataMode(uint8_t data_mode)
Sets the SPI data mode.
SPISettings::SPISettings
SPISettings()
SPISettings constructor.
Definition: SPIBCM.h:78
SPIBCMClass::end
static void end()
End SPI operations.
SPIBCMClass::begin
static void begin()
Start SPI operations.
SPIBCMClass::usingInterrupt
static void usingInterrupt(uint8_t interruptNumber)
Not implemented.
SPISettings::cdiv
uint16_t cdiv
SPI clock divider.
Definition: SPIBCM.h:135
SPISettings::dmode
uint8_t dmode
SPI data mode.
Definition: SPIBCM.h:137