webgcode

Форк
0
143 строки · 5.1 Кб
1
#include "stm32f4xx_conf.h"
2
#include "cnc.h"
3
#include "core_cm4.h"
4
#include "core_cmInstr.h"
5

6
static const struct {
7
    GPIO_TypeDef *gpio;
8
    uint32_t gpioAhb1Periph;
9
    SPI_TypeDef *spi;
10
    uint8_t spiAlternateFunction;
11
    uint32_t spiApb1Periph;
12
    uint16_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
26
static 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
35
static 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

45
static uint16_t myLog2(int value) {
46
    return 31 - __builtin_clz(value);
47
}
48

49
void initSPISystem() {
50
    RCC_APB1PeriphClockCmd(spiPinout.spiApb1Periph, ENABLE);
51
    RCC_AHB1PeriphClockCmd(spiPinout.gpioAhb1Periph, ENABLE);
52
    GPIO_PinAFConfig(spiPinout.gpio, myLog2(spiPinout.spiClock), spiPinout.spiAlternateFunction);
53
    GPIO_PinAFConfig(spiPinout.gpio, myLog2(spiPinout.spiMosi), spiPinout.spiAlternateFunction);
54
    GPIO_PinAFConfig(spiPinout.gpio, myLog2(spiPinout.spiMiso), spiPinout.spiAlternateFunction);
55
    GPIO_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});
60
    GPIO_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});
66
    GPIO_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});
72
    SPI_I2S_DeInit(spiPinout.spi);
73
    SPI_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
    });
84
    SPI_TIModeCmd(spiPinout.spi, DISABLE);
85
    SPI_Cmd(spiPinout.spi, ENABLE);
86
}
87

88
static void flashShiftRegisters() {
89
    GPIO_ResetBits(spiPinout.gpio, spiPinout.spiEnablePin);
90
    GPIO_SetBits(spiPinout.gpio, spiPinout.spiEnablePin);
91
}
92

93
void handleSPI() {
94
    crBegin;
95
            flashShiftRegisters();
96
            SPI_I2S_SendData(spiPinout.spi, ((spi_output_serializer_t) {.s=cncMemory.spiOutput}).n ^ ~((spi_output_serializer_t) {.s = spiOutputPolarity}).n);
97
            while ((spiPinout.spi->SR & SPI_SR_TXE) == 0)
98
                crYield();
99
            while ((spiPinout.spi->SR & SPI_SR_RXNE) == 0)
100
                crYield();
101
            cncMemory.unfilteredSpiInput = (uint8_t) SPI_I2S_ReceiveData(spiPinout.spi) ^ ~((spi_input_serializer_t) {.s = spiInputPolarity}).n;
102
            while ((spiPinout.spi->SR & SPI_SR_BSY) != 0)
103
                crYield();
104
            flashShiftRegisters();
105
    crFinish;
106
}
107

108
static 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.
113
    static uint64_t discrepancyStartTick = 0;
114
    crBegin;
115
            discrepancyStartTick += cncMemory.tick;
116
            while (cncMemory.tick < discrepancyStartTick + 20000) {
117
                if (!(cncMemory.spiOutput.run) || cncMemory.spiInput.upf)
118
                    crReturn();
119
                crYield();
120
            }
121
            cncMemory.spiOutput.run = 1;
122
    crFinish;
123
}
124

125
static int32_t spiInputFilter[8] = {0, 0, 0, 0, 0, 0, 0, 0};
126

127
static void filterSpiInput(int32_t tickDifference) {
128
    uint8_t result = 0;
129
    for (int i = 0; i < 8; i++) {
130
        spiInputFilter[i] = __SSAT(spiInputFilter[i] + (cncMemory.unfilteredSpiInput & (1 << i) ? tickDifference : -tickDifference), 2);
131
        result |= (spiInputFilter[i] > 0) << i;
132
    }
133
    cncMemory.spiInput = ((spi_input_serializer_t) {.n=result}).s;
134
}
135

136
void periodicSpiFunction() {
137
    static uint64_t lastTick;
138
    uint64_t tick = cncMemory.tick;
139
    int32_t tickDifference = (uint32_t) (tick - lastTick);
140
    lastTick = tick;
141
    debounceRunbit();
142
    filterSpiInput(tickDifference);
143
}

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.