104 lines
2.6 KiB
C++
104 lines
2.6 KiB
C++
#include "system.h"
|
|
#include "spiclass.h"
|
|
typedef __SIZE_TYPE__ size_t;
|
|
|
|
enum SPICLK : uint32_t {
|
|
FPCLK_2 = 0u, // 72 MHz
|
|
FPCLK_4, // 72 MHz
|
|
FPCLK_8, // 36 MHz
|
|
FPCLK_16, // 18 MHz
|
|
FPCLK_32, // 9 MHz
|
|
FPCLK_64, // 4.5 MHz
|
|
FPCLK_128, // 2.25 MHz
|
|
FPCLK_256, // 1.125 MHz
|
|
};
|
|
|
|
static SpiClass * pSpiInstance = nullptr;
|
|
extern "C" {
|
|
[[gnu::interrupt]] extern void SPI1_IRQHandler ();
|
|
extern void * memcpy (void * dest, const void * src, size_t n);
|
|
};
|
|
void SPI1_IRQHandler () {
|
|
if (pSpiInstance) pSpiInstance->irq();
|
|
}
|
|
static void InitPins () noexcept {
|
|
// PA4 - NSS (software), PA5 - SCK, PA6 - MISO, PA7 - MOSI
|
|
GPIOA.CFGLR.modify([](GPIOA_Type::CFGLR_DEF & r) -> uint32_t {
|
|
r.B.MODE4 = 3u; // 50 MHz
|
|
r.B.CNF4 = 0u; // gen push - pull
|
|
r.B.MODE5 = 3u; // 50 MHz
|
|
r.B.CNF5 = 3u; // alt push - pull
|
|
|
|
r.B.MODE6 = 0u; // input mode
|
|
r.B.CNF6 = 1u; // floating
|
|
r.B.MODE7 = 3u; // 50 MHz
|
|
r.B.CNF7 = 3u; // alt push - pull
|
|
return r.R;
|
|
});
|
|
// AFIO - default
|
|
}
|
|
void SpiClass::irq() {
|
|
if (SPI1.STATR.B.RXNE) {
|
|
buffer [index++] = SPI1.DATAR.R;
|
|
if (index == total) {
|
|
complete = true;
|
|
index = 0u;
|
|
select (true);
|
|
return;
|
|
}
|
|
// tady by mělo být už odesláno
|
|
SPI1.DATAR.R = buffer [index];
|
|
}
|
|
}
|
|
|
|
SpiClass::SpiClass() noexcept : index(0u), total(0u), complete (false) {
|
|
pSpiInstance = this;
|
|
RCC.APB2PCENR.modify([](RCC_Type::APB2PCENR_DEF & r) -> uint32_t {
|
|
r.B.SPI1EN = SET;
|
|
r.B.IOPAEN = SET;
|
|
r.B.AFIOEN = SET;
|
|
return r.R;
|
|
});
|
|
InitPins();
|
|
select (true);
|
|
SPI1.CTLR1.modify([](SPI1_Type::CTLR1_DEF & r) -> uint32_t {
|
|
r.B.CPHA = SET;
|
|
r.B.CPOL = SET;
|
|
r.B.MSTR = SET;
|
|
r.B.DFF = RESET; // 8 bit
|
|
r.B.SSM = SET;
|
|
r.B.SSI = SET;
|
|
r.B.LSBFIRST = RESET;
|
|
r.B.BR = FPCLK_64; // 4.5 MHz
|
|
return r.R;
|
|
});
|
|
SPI1.CTLR2.modify([](SPI1_Type::CTLR2_DEF & r) -> uint32_t {
|
|
r.B.SSOE = SET;
|
|
r.B.RXNEIE = SET;
|
|
return r.R;
|
|
});
|
|
NVIC.EnableIRQ(SPI1_IRQn);
|
|
SPI1.CTLR1.B.SPE = SET;
|
|
}
|
|
void SpiClass::select (const bool set) const noexcept {
|
|
if (set) GPIOA.BSHR.B.BS4 = SET;
|
|
else GPIOA.BSHR.B.BR4 = SET;
|
|
}
|
|
|
|
bool SpiClass::send (const char * data, const unsigned int len) {
|
|
if (!complete) return false;
|
|
select (false);
|
|
complete = false;
|
|
index = 0u;
|
|
total = len > SPIBUFLEN ? SPIBUFLEN : len;
|
|
memcpy (buffer, data, total);
|
|
SPI1.DATAR.R = buffer [index];
|
|
|
|
return true;
|
|
}
|
|
char * SpiClass::received (unsigned int & count) {
|
|
if (complete) count = total;
|
|
else count = 0;
|
|
return buffer;
|
|
}
|
|
|