Packages
Basic library that enables easy interaction with the PRU cores present in the BeagleBone Black.
Current section
Files
Jump to
Current section
Files
pru/lib/softspic/spi-devs.c
#include <stdint.h>
#include "spi-devs.h"
#define SPI_CLOCK_MASK(value) (value^pins.sck_dir)
#define SPI_UNPACK(value, idx) ( (value >> idx) & 0x1 )
#ifndef SPI_CUSTOM_TIMING_CALLBACK
void spi_delay(uint32_t time) { while (--time) __delay_cycles(10); }
#else
extern void spi_delay(uint32_t time);
#endif // SPI_TIMING_CALLBACK
// clock standard
inline void spi_clock_tick(SpiPins_t pins) { digitalWrite((uint32_t)pins.sck, SPI_CLOCK_MASK(HIGH));}
inline void spi_clock_tock(SpiPins_t pins) { digitalWrite((uint32_t)pins.sck, SPI_CLOCK_MASK(LOW));}
inline uint32_t spi_reverse_bits(uint32_t value)
{
uint32_t word = 0;
for (uint8_t i = 0; i < sizeof(uint32_t); i++) {
word = (word << 1) | ((value >> i) & 0x1);
}
return word;
}
// ========================================================================== //
// SPI Xfer
// ========================================================================== //
/* uint8_t SpiXferTxClockRise_xfer_cycle(uint32_t value) */
inline bool spi_bit_cpha1(bool value, SpiPins_t pins, SpiTimings_t timings)
{
bool read = 0;
spi_clock_tick(pins);
/* spi_delay(timings.c0); /\* Timings::delayCyclesP0(); *\/ */
digitalWrite((uint32_t)pins.mosi, value);
// when DataTxEdge == TxClockRise (CPOL=1) data will be captured at falling edge propagation
spi_delay(timings.c1); /* Timings::delayCyclesP1(); */
spi_clock_tock(pins); /* Clock::template tock<SpiPins_t>(); */
// holding low, so there is enough time for data preparation and changing */
spi_delay(timings.c0); /* Timings::delayCyclesC0(); */
read = digitalRead(pins.miso); // reading at the middle of SCK pulse
// wait until data is fetched by slave device, while SCK low, checking DATAsheet for this interval
/* spi_delay(timings.c1); /\* Timings::delayCyclesC1(); *\/ */
return read;
}
/* uint8_t SpiXferTxClockFall_xfer_cycle(uint32_t value) */
inline bool spi_bit_cpha0(bool value, SpiPins_t pins, SpiTimings_t timings)
{
bool read = 0;
// changing MOSI big while SCK low, propogation
digitalWrite((uint32_t)pins.mosi, value);
// there is a requirement that LOW and HIGH have identical interval!
spi_delay(timings.c1); /* Timings::delayCyclesP1(); */
spi_clock_tick(pins); /* Clock::template tick<SpiPins_t>(); */
// reading at the middle of SCK pulse
spi_delay(timings.c0); /* Timings::delayCyclesC0(); */
read = digitalRead(pins.miso); // reading at the middle of SCK pulse
// wait until data is fetched by slave device, while SCK high, checking DATAsheet for this interval
/* spi_delay(timings.c1); /\* Timings::delayCyclesC1(); *\/ */
spi_clock_tock(pins); /* Clock::template tock<SpiPins_t>(); */
// holding low, so there is enough time for data preparation and changing
/* spi_delay(timings.c0); /\* Timings::delayCyclesP0(); *\/ */
return read;
}
uint32_t spi_xfer_cpha0(uint32_t data, uint8_t bit_count, SpiPins_t pins, SpiTimings_t timings) {
uint32_t result = 0;
// Ensure MOSI lines low
digitalWrite((uint32_t)pins.mosi, LOW);
// Start xfer cycle
spi_clock_tock(pins); // Clock::template tock<SpiPins_t>();
// Here, delay is added, to make CPHA=1 and CPHA=0 both work!
spi_delay(timings.pre); // Timings::delayCyclesPre();
for (uint8_t idx = 0; idx < bit_count; idx++)
result = (result << 1) | spi_bit_cpha0(SPI_UNPACK(data, idx), pins, timings);
digitalWrite((uint32_t)pins.mosi, LOW);
// Leave MOSI lines low
spi_delay(timings.post);
return result;
}
uint32_t spi_xfer_cpha1(uint32_t data, uint8_t bit_count, SpiPins_t pins, SpiTimings_t timings) {
uint32_t result = 0;
// Ensure MOSI lines low
digitalWrite((uint32_t)pins.mosi, LOW);
// Start xfer cycle
spi_clock_tock(pins); // Clock::template tock<SpiPins_t>();
// Here, delay is added, to make CPHA=1 and CPHA=0 both work!
spi_delay(timings.pre); // Timings::delayCyclesPre();
for (uint8_t idx = 0; idx < bit_count; idx++)
result = (result << 1) | spi_bit_cpha1(SPI_UNPACK(data, idx), pins, timings);
// Leave MOSI lines low
digitalWrite((uint32_t)pins.mosi, LOW);
spi_delay(timings.post);
return result;
}