<commit_before>// Copyright Microsoft Corporation
// Copyright Oberon microsystems, Inc
// Copyright GHI Electronics, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "STM32F4.h"
#include <string.h>

bool STM32F4_Spi_Transaction_Start(int32_t controllerIndex);
bool STM32F4_Spi_Transaction_Stop(int32_t controllerIndex);
bool STM32F4_Spi_Transaction_nWrite8_nRead8(int32_t controllerIndex);

typedef  SPI_TypeDef* ptr_SPI_TypeDef;

#define DATA_BIT_LENGTH_16  16
#define DATA_BIT_LENGTH_8   8

static const STM32F4_Gpio_Pin spiClkPins[] = STM32F4_SPI_SCLK_PINS;
static const STM32F4_Gpio_Pin spiMisoPins[] = STM32F4_SPI_MISO_PINS;
static const STM32F4_Gpio_Pin spiMosiPins[] = STM32F4_SPI_MOSI_PINS;

static ptr_SPI_TypeDef spiPortRegs[TOTAL_SPI_CONTROLLERS];

const char* spiApiNames[TOTAL_SPI_CONTROLLERS] = {
#if TOTAL_SPI_CONTROLLERS > 0
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\0",
#if TOTAL_SPI_CONTROLLERS > 1
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\1",
#if TOTAL_SPI_CONTROLLERS > 2
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\2",
#if TOTAL_SPI_CONTROLLERS > 3
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\3",
#if TOTAL_SPI_CONTROLLERS > 4
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\4",
#endif
#endif
#endif
#endif
#endif
};

struct SpiState {
    int32_t controllerIndex;

    uint8_t *readBuffer;
    uint8_t *writeBuffer;

    size_t readLength;
    size_t writeLength;

    int32_t chipSelectLine;
    int32_t dataBitLength;
    int32_t clockFrequency;

    uint32_t chipSelectSetupTime;
    uint32_t chipSelectHoldTime;
    TinyCLR_Spi_ChipSelectType chipSelectType;

    bool chipSelectActiveState;

    TinyCLR_Spi_Mode spiMode;

    uint16_t initializeCount;
};

static SpiState spiStates[TOTAL_SPI_CONTROLLERS];

static TinyCLR_Spi_Controller spiControllers[TOTAL_SPI_CONTROLLERS];
static TinyCLR_Api_Info spiApi[TOTAL_SPI_CONTROLLERS];

void STM32F4_Spi_AddApi(const TinyCLR_Api_Manager* apiManager) {
    for (auto i = 0; i < TOTAL_SPI_CONTROLLERS; i++) {
        spiControllers[i].ApiInfo = &spiApi[i];
        spiControllers[i].Acquire = &STM32F4_Spi_Acquire;
        spiControllers[i].Release = &STM32F4_Spi_Release;
        spiControllers[i].WriteRead = &STM32F4_Spi_WriteRead;
        spiControllers[i].SetActiveSettings = &STM32F4_Spi_SetActiveSettings;
        spiControllers[i].GetChipSelectLineCount = &STM32F4_Spi_GetChipSelectLineCount;
        spiControllers[i].GetMinClockFrequency = &STM32F4_Spi_GetMinClockFrequency;
        spiControllers[i].GetMaxClockFrequency = &STM32F4_Spi_GetMaxClockFrequency;
        spiControllers[i].GetSupportedDataBitLengths = &STM32F4_Spi_GetSupportedDataBitLengths;

        spiApi[i].Author = "GHI Electronics, LLC";
        spiApi[i].Name = spiApiNames[i];
        spiApi[i].Type = TinyCLR_Api_Type::SpiController;
        spiApi[i].Version = 0;
        spiApi[i].Implementation = &spiControllers[i];
        spiApi[i].State = &spiStates[i];

        spiStates[i].controllerIndex = i;

        apiManager->Add(apiManager, &spiApi[i]);
    }

#ifdef SPI1
    if (TOTAL_SPI_CONTROLLERS > 0) spiPortRegs[0] = SPI1;
#ifdef SPI2
    if (TOTAL_SPI_CONTROLLERS > 1) spiPortRegs[1] = SPI2;
#ifdef SPI3
    if (TOTAL_SPI_CONTROLLERS > 2) spiPortRegs[2] = SPI3;
#ifdef SPI4
    if (TOTAL_SPI_CONTROLLERS > 3) spiPortRegs[3] = SPI4;
#ifdef SPI5
    if (TOTAL_SPI_CONTROLLERS > 4) spiPortRegs[4] = SPI5;
#ifdef SPI6
    if (TOTAL_SPI_CONTROLLERS > 5) spiPortRegs[5] = SPI6;
#endif
#endif
#endif
#endif
#endif
#endif
}

bool STM32F4_Spi_Transaction_Start(int32_t controllerIndex) {
    auto state = &spiStates[controllerIndex];

    STM32F4_GpioInternal_WritePin(state->chipSelectLine, state->chipSelectActiveState);

    if (state->chipSelectSetupTime > 0) {
        auto currentTicks = STM32F4_Time_GetCurrentProcessorTime();

        while (STM32F4_Time_GetCurrentProcessorTime() - currentTicks < state->chipSelectSetupTime);
    }

    return true;
}

bool STM32F4_Spi_Transaction_Stop(int32_t controllerIndex) {
    auto state = &spiStates[controllerIndex];

    ptr_SPI_TypeDef spi = spiPortRegs[controllerIndex];

    while (spi->SR & SPI_SR_BSY); // wait for completion

    if (state->chipSelectHoldTime > 0) {
        auto currentTicks = STM32F4_Time_GetCurrentProcessorTime();

        while (STM32F4_Time_GetCurrentProcessorTime() - currentTicks < state->chipSelectHoldTime);
    }

    STM32F4_GpioInternal_WritePin(state->chipSelectLine, !state->chipSelectActiveState);


    return true;
}


bool STM32F4_Spi_Transaction_nWrite8_nRead8(int32_t controllerIndex) {
    auto state = &spiStates[controllerIndex];<commit_msg>If no setup hold time, keep default (same as previous release - delay 1 clock).<commit_after>// Copyright Microsoft Corporation
// Copyright Oberon microsystems, Inc
// Copyright GHI Electronics, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "STM32F4.h"
#include <string.h>

bool STM32F4_Spi_Transaction_Start(int32_t controllerIndex);
bool STM32F4_Spi_Transaction_Stop(int32_t controllerIndex);
bool STM32F4_Spi_Transaction_nWrite8_nRead8(int32_t controllerIndex);

typedef  SPI_TypeDef* ptr_SPI_TypeDef;

#define DATA_BIT_LENGTH_16  16
#define DATA_BIT_LENGTH_8   8

static const STM32F4_Gpio_Pin spiClkPins[] = STM32F4_SPI_SCLK_PINS;
static const STM32F4_Gpio_Pin spiMisoPins[] = STM32F4_SPI_MISO_PINS;
static const STM32F4_Gpio_Pin spiMosiPins[] = STM32F4_SPI_MOSI_PINS;

static ptr_SPI_TypeDef spiPortRegs[TOTAL_SPI_CONTROLLERS];

const char* spiApiNames[TOTAL_SPI_CONTROLLERS] = {
#if TOTAL_SPI_CONTROLLERS > 0
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\0",
#if TOTAL_SPI_CONTROLLERS > 1
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\1",
#if TOTAL_SPI_CONTROLLERS > 2
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\2",
#if TOTAL_SPI_CONTROLLERS > 3
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\3",
#if TOTAL_SPI_CONTROLLERS > 4
"GHIElectronics.TinyCLR.NativeApis.STM32F4.SpiController\\4",
#endif
#endif
#endif
#endif
#endif
};

struct SpiState {
    int32_t controllerIndex;

    uint8_t *readBuffer;
    uint8_t *writeBuffer;

    size_t readLength;
    size_t writeLength;

    int32_t chipSelectLine;
    int32_t dataBitLength;
    int32_t clockFrequency;

    uint32_t chipSelectSetupTime;
    uint32_t chipSelectHoldTime;
    TinyCLR_Spi_ChipSelectType chipSelectType;

    bool chipSelectActiveState;

    TinyCLR_Spi_Mode spiMode;

    uint16_t initializeCount;
};

static SpiState spiStates[TOTAL_SPI_CONTROLLERS];

static TinyCLR_Spi_Controller spiControllers[TOTAL_SPI_CONTROLLERS];
static TinyCLR_Api_Info spiApi[TOTAL_SPI_CONTROLLERS];

void STM32F4_Spi_AddApi(const TinyCLR_Api_Manager* apiManager) {
    for (auto i = 0; i < TOTAL_SPI_CONTROLLERS; i++) {
        spiControllers[i].ApiInfo = &spiApi[i];
        spiControllers[i].Acquire = &STM32F4_Spi_Acquire;
        spiControllers[i].Release = &STM32F4_Spi_Release;
        spiControllers[i].WriteRead = &STM32F4_Spi_WriteRead;
        spiControllers[i].SetActiveSettings = &STM32F4_Spi_SetActiveSettings;
        spiControllers[i].GetChipSelectLineCount = &STM32F4_Spi_GetChipSelectLineCount;
        spiControllers[i].GetMinClockFrequency = &STM32F4_Spi_GetMinClockFrequency;
        spiControllers[i].GetMaxClockFrequency = &STM32F4_Spi_GetMaxClockFrequency;
        spiControllers[i].GetSupportedDataBitLengths = &STM32F4_Spi_GetSupportedDataBitLengths;

        spiApi[i].Author = "GHI Electronics, LLC";
        spiApi[i].Name = spiApiNames[i];
        spiApi[i].Type = TinyCLR_Api_Type::SpiController;
        spiApi[i].Version = 0;
        spiApi[i].Implementation = &spiControllers[i];
        spiApi[i].State = &spiStates[i];

        spiStates[i].controllerIndex = i;

        apiManager->Add(apiManager, &spiApi[i]);
    }

#ifdef SPI1
    if (TOTAL_SPI_CONTROLLERS > 0) spiPortRegs[0] = SPI1;
#ifdef SPI2
    if (TOTAL_SPI_CONTROLLERS > 1) spiPortRegs[1] = SPI2;
#ifdef SPI3
    if (TOTAL_SPI_CONTROLLERS > 2) spiPortRegs[2] = SPI3;
#ifdef SPI4
    if (TOTAL_SPI_CONTROLLERS > 3) spiPortRegs[3] = SPI4;
#ifdef SPI5
    if (TOTAL_SPI_CONTROLLERS > 4) spiPortRegs[4] = SPI5;
#ifdef SPI6
    if (TOTAL_SPI_CONTROLLERS > 5) spiPortRegs[5] = SPI6;
#endif
#endif
#endif
#endif
#endif
#endif
}

bool STM32F4_Spi_Transaction_Start(int32_t controllerIndex) {
    auto state = &spiStates[controllerIndex];

    STM32F4_GpioInternal_WritePin(state->chipSelectLine, state->chipSelectActiveState);

    if (state->chipSelectSetupTime > 0) {
        auto currentTicks = STM32F4_Time_GetCurrentProcessorTime();

        while (STM32F4_Time_GetCurrentProcessorTime() - currentTicks < state->chipSelectSetupTime);
    }
    else {
        STM32F4_Time_Delay(nullptr, ((1000000 / (state->clockFrequency / 1000)) / 1000));
    }

    return true;
}

bool STM32F4_Spi_Transaction_Stop(int32_t controllerIndex) {
    auto state = &spiStates[controllerIndex];

    ptr_SPI_TypeDef spi = spiPortRegs[controllerIndex];

    while (spi->SR & SPI_SR_BSY); // wait for completion

    if (state->chipSelectHoldTime > 0) {
        auto currentTicks = STM32F4_Time_GetCurrentProcessorTime();

        while (STM32F4_Time_GetCurrentProcessorTime() - currentTicks < state->chipSelectHoldTime);
    }

    else {
        STM32F4_Time_Delay(nullptr, ((1000000 / (state->clockFrequency / 1000)) / 1000));
    }

    STM32F4_GpioInternal_WritePin(state->chipSelectLine, !state->chipSelectActiveState);


    return true;
}


bool STM32F4_Spi_Transaction_nWrite8_nRead8(int32_t controllerIndex) {
    auto state = &spiStates[controllerIndex];
{'fraction_non_alphanumeric': 0.09165963035932076, 'fraction_numerical': 0.03705788535509898, 'mean_word_length': 4.749730312837109, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2626180', 'n_tokens_mistral': 4160, 'n_tokens_neox': 3825, 'n_words': 718}