webgcode
143 строки · 5.1 Кб
1#include "stm32f4xx_conf.h"
2#include "cnc.h"
3#include "core_cm4.h"
4#include "core_cmInstr.h"
5
6static const struct {
7GPIO_TypeDef *gpio;
8uint32_t gpioAhb1Periph;
9SPI_TypeDef *spi;
10uint8_t spiAlternateFunction;
11uint32_t spiApb1Periph;
12uint16_t spiClock, spiMosi, spiMiso, spiEnablePin;
13} spiPinout = {
14.gpio = GPIOB,
15.gpioAhb1Periph = RCC_AHB1Periph_GPIOB,
16.spi = SPI2,
17.spiAlternateFunction = GPIO_AF_SPI2,
18.spiApb1Periph = RCC_APB1Periph_SPI2,
19.spiClock = GPIO_Pin_13,
20.spiMosi = GPIO_Pin_15,
21.spiMiso = GPIO_Pin_14,
22.spiEnablePin = GPIO_Pin_12
23};
24
25// 1 -> high is true, 0 -> low is true
26static const spi_input_t spiInputPolarity = {
27.drv = 0,
28.upf = 0,
29.limitX = 1,
30.limitY = 1,
31.limitZ = 1
32};
33
34// 1 -> high is true, 0 -> low is true
35static const spi_output_t spiOutputPolarity = {
36.run = 1,
37.reverse = 1,
38.reset = 1,
39.sph = 1,
40.spm = 1,
41.spl = 1,
42.socket = 0
43};
44
45static uint16_t myLog2(int value) {
46return 31 - __builtin_clz(value);
47}
48
49void initSPISystem() {
50RCC_APB1PeriphClockCmd(spiPinout.spiApb1Periph, ENABLE);
51RCC_AHB1PeriphClockCmd(spiPinout.gpioAhb1Periph, ENABLE);
52GPIO_PinAFConfig(spiPinout.gpio, myLog2(spiPinout.spiClock), spiPinout.spiAlternateFunction);
53GPIO_PinAFConfig(spiPinout.gpio, myLog2(spiPinout.spiMosi), spiPinout.spiAlternateFunction);
54GPIO_PinAFConfig(spiPinout.gpio, myLog2(spiPinout.spiMiso), spiPinout.spiAlternateFunction);
55GPIO_Init(spiPinout.gpio, &(GPIO_InitTypeDef) {
56.GPIO_Pin = spiPinout.spiEnablePin,
57.GPIO_Mode = GPIO_Mode_OUT,
58.GPIO_Speed = GPIO_Speed_100MHz,
59.GPIO_OType = GPIO_OType_PP});
60GPIO_Init(spiPinout.gpio, &(GPIO_InitTypeDef) {
61.GPIO_Pin = spiPinout.spiClock | spiPinout.spiMosi,
62.GPIO_Mode = GPIO_Mode_AF,
63.GPIO_Speed = GPIO_Speed_100MHz,
64.GPIO_OType = GPIO_OType_PP,
65.GPIO_PuPd = GPIO_PuPd_DOWN});
66GPIO_Init(spiPinout.gpio, &(GPIO_InitTypeDef) {
67.GPIO_Pin = spiPinout.spiMiso,
68.GPIO_Mode = GPIO_Mode_AF,
69.GPIO_Speed = GPIO_Speed_100MHz,
70.GPIO_OType = GPIO_OType_PP,
71.GPIO_PuPd = GPIO_PuPd_NOPULL});
72SPI_I2S_DeInit(spiPinout.spi);
73SPI_Init(spiPinout.spi, &(SPI_InitTypeDef) {
74.SPI_Mode = SPI_Mode_Master,
75.SPI_Direction = SPI_Direction_2Lines_FullDuplex,
76.SPI_DataSize = SPI_DataSize_8b,
77.SPI_CPOL = SPI_CPOL_High,
78.SPI_CPHA = SPI_CPHA_1Edge,
79.SPI_NSS = SPI_NSS_Soft,
80.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4,
81.SPI_FirstBit = SPI_FirstBit_MSB,
82.SPI_CRCPolynomial = 7
83});
84SPI_TIModeCmd(spiPinout.spi, DISABLE);
85SPI_Cmd(spiPinout.spi, ENABLE);
86}
87
88static void flashShiftRegisters() {
89GPIO_ResetBits(spiPinout.gpio, spiPinout.spiEnablePin);
90GPIO_SetBits(spiPinout.gpio, spiPinout.spiEnablePin);
91}
92
93void handleSPI() {
94crBegin;
95flashShiftRegisters();
96SPI_I2S_SendData(spiPinout.spi, ((spi_output_serializer_t) {.s=cncMemory.spiOutput}).n ^ ~((spi_output_serializer_t) {.s = spiOutputPolarity}).n);
97while ((spiPinout.spi->SR & SPI_SR_TXE) == 0)
98crYield();
99while ((spiPinout.spi->SR & SPI_SR_RXNE) == 0)
100crYield();
101cncMemory.unfilteredSpiInput = (uint8_t) SPI_I2S_ReceiveData(spiPinout.spi) ^ ~((spi_input_serializer_t) {.s = spiInputPolarity}).n;
102while ((spiPinout.spi->SR & SPI_SR_BSY) != 0)
103crYield();
104flashShiftRegisters();
105crFinish;
106}
107
108static void debounceRunbit() {
109// when the spindle is stopped (sometimes by other means than a low signal on spindleOutput.run,
110// like estop signal, or the interface stop button), we need to release the "run" signal.
111// but there is a delay between when we set the 'run' signal and when the spindle answers with the "spindle running" signal
112// so we wait a bit.
113static uint64_t discrepancyStartTick = 0;
114crBegin;
115discrepancyStartTick += cncMemory.tick;
116while (cncMemory.tick < discrepancyStartTick + 20000) {
117if (!(cncMemory.spiOutput.run) || cncMemory.spiInput.upf)
118crReturn();
119crYield();
120}
121cncMemory.spiOutput.run = 1;
122crFinish;
123}
124
125static int32_t spiInputFilter[8] = {0, 0, 0, 0, 0, 0, 0, 0};
126
127static void filterSpiInput(int32_t tickDifference) {
128uint8_t result = 0;
129for (int i = 0; i < 8; i++) {
130spiInputFilter[i] = __SSAT(spiInputFilter[i] + (cncMemory.unfilteredSpiInput & (1 << i) ? tickDifference : -tickDifference), 2);
131result |= (spiInputFilter[i] > 0) << i;
132}
133cncMemory.spiInput = ((spi_input_serializer_t) {.n=result}).s;
134}
135
136void periodicSpiFunction() {
137static uint64_t lastTick;
138uint64_t tick = cncMemory.tick;
139int32_t tickDifference = (uint32_t) (tick - lastTick);
140lastTick = tick;
141debounceRunbit();
142filterSpiInput(tickDifference);
143}