/******************************************************************************* CAN FD SPI Driver: Implementation Company: Microchip Technology Inc. File Name: drv_canfdspi_api.c Summary: API implementation. Description: . *******************************************************************************/ //DOM-IGNORE-BEGIN /******************************************************************************* Copyright (c) 2018 Microchip Technology Inc. and its subsidiaries. Subject to your compliance with these terms, you may use Microchip software and any derivatives exclusively with Microchip products. It is your responsibility to comply with third party license terms applicable to your use of third party software (including open source software) that may accompany Microchip software. THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE. *******************************************************************************/ //DOM-IGNORE-END // ***************************************************************************** // ***************************************************************************** // Section: Included Files #include "mcp2518fd_canfdspi_api.h" #include extern SPIClass* pSPI; #define spi_readwrite pSPI->transfer #define spi_read() spi_readwrite(0x00) #define spi_write(spi_val) spi_readwrite(spi_val) #define SPI_BEGIN() pSPI->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)) #define SPI_END() pSPI->endTransaction(); // ***************************************************************************** // ***************************************************************************** // Section: Defines #define CRCBASE 0xFFFF #define CRCUPPER 1 // ***************************************************************************** // ***************************************************************************** // Section: Variables //! SPI Transmit buffer uint8_t spiTransmitBuffer[SPI_DEFAULT_BUFFER_LENGTH+2]; //! SPI Receive buffer uint8_t spiReceiveBuffer[SPI_DEFAULT_BUFFER_LENGTH]; //! Reverse order of bits in byte const uint8_t BitReverseTable256[256] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; //! Look-up table for CRC calculation const uint16_t crc16_table[256] = { 0x0000, 0x8005, 0x800F, 0x000A, 0x801B, 0x001E, 0x0014, 0x8011, 0x8033, 0x0036, 0x003C, 0x8039, 0x0028, 0x802D, 0x8027, 0x0022, 0x8063, 0x0066, 0x006C, 0x8069, 0x0078, 0x807D, 0x8077, 0x0072, 0x0050, 0x8055, 0x805F, 0x005A, 0x804B, 0x004E, 0x0044, 0x8041, 0x80C3, 0x00C6, 0x00CC, 0x80C9, 0x00D8, 0x80DD, 0x80D7, 0x00D2, 0x00F0, 0x80F5, 0x80FF, 0x00FA, 0x80EB, 0x00EE, 0x00E4, 0x80E1, 0x00A0, 0x80A5, 0x80AF, 0x00AA, 0x80BB, 0x00BE, 0x00B4, 0x80B1, 0x8093, 0x0096, 0x009C, 0x8099, 0x0088, 0x808D, 0x8087, 0x0082, 0x8183, 0x0186, 0x018C, 0x8189, 0x0198, 0x819D, 0x8197, 0x0192, 0x01B0, 0x81B5, 0x81BF, 0x01BA, 0x81AB, 0x01AE, 0x01A4, 0x81A1, 0x01E0, 0x81E5, 0x81EF, 0x01EA, 0x81FB, 0x01FE, 0x01F4, 0x81F1, 0x81D3, 0x01D6, 0x01DC, 0x81D9, 0x01C8, 0x81CD, 0x81C7, 0x01C2, 0x0140, 0x8145, 0x814F, 0x014A, 0x815B, 0x015E, 0x0154, 0x8151, 0x8173, 0x0176, 0x017C, 0x8179, 0x0168, 0x816D, 0x8167, 0x0162, 0x8123, 0x0126, 0x012C, 0x8129, 0x0138, 0x813D, 0x8137, 0x0132, 0x0110, 0x8115, 0x811F, 0x011A, 0x810B, 0x010E, 0x0104, 0x8101, 0x8303, 0x0306, 0x030C, 0x8309, 0x0318, 0x831D, 0x8317, 0x0312, 0x0330, 0x8335, 0x833F, 0x033A, 0x832B, 0x032E, 0x0324, 0x8321, 0x0360, 0x8365, 0x836F, 0x036A, 0x837B, 0x037E, 0x0374, 0x8371, 0x8353, 0x0356, 0x035C, 0x8359, 0x0348, 0x834D, 0x8347, 0x0342, 0x03C0, 0x83C5, 0x83CF, 0x03CA, 0x83DB, 0x03DE, 0x03D4, 0x83D1, 0x83F3, 0x03F6, 0x03FC, 0x83F9, 0x03E8, 0x83ED, 0x83E7, 0x03E2, 0x83A3, 0x03A6, 0x03AC, 0x83A9, 0x03B8, 0x83BD, 0x83B7, 0x03B2, 0x0390, 0x8395, 0x839F, 0x039A, 0x838B, 0x038E, 0x0384, 0x8381, 0x0280, 0x8285, 0x828F, 0x028A, 0x829B, 0x029E, 0x0294, 0x8291, 0x82B3, 0x02B6, 0x02BC, 0x82B9, 0x02A8, 0x82AD, 0x82A7, 0x02A2, 0x82E3, 0x02E6, 0x02EC, 0x82E9, 0x02F8, 0x82FD, 0x82F7, 0x02F2, 0x02D0, 0x82D5, 0x82DF, 0x02DA, 0x82CB, 0x02CE, 0x02C4, 0x82C1, 0x8243, 0x0246, 0x024C, 0x8249, 0x0258, 0x825D, 0x8257, 0x0252, 0x0270, 0x8275, 0x827F, 0x027A, 0x826B, 0x026E, 0x0264, 0x8261, 0x0220, 0x8225, 0x822F, 0x022A, 0x823B, 0x023E, 0x0234, 0x8231, 0x8213, 0x0216, 0x021C, 0x8219, 0x0208, 0x820D, 0x8207, 0x0202 }; // ***************************************************************************** // ***************************************************************************** // Section: Reset int8_t DRV_CANFDSPI_Reset(CANFDSPI_MODULE_ID index) { uint16_t spiTransferSize = 2; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) (cINSTRUCTION_RESET << 4); spiTransmitBuffer[1] = 0; #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: SPI Access Functions int8_t DRV_CANFDSPI_ReadByte(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t *rxd) { uint16_t spiTransferSize = 3; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); spiTransmitBuffer[2] = 0; #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spiReceiveBuffer[2] = spi_readwrite(0x00); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); Serial.printf("DRV_CANFDSPI_ReadByte = %d\n\r",spiReceiveBuffer[2]); // Update data *rxd = spiReceiveBuffer[2]; return spiTransferError; } int8_t DRV_CANFDSPI_WriteByte(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t txd) { uint16_t spiTransferSize = 3; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); spiTransmitBuffer[2] = txd; #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_ReadWord(CANFDSPI_MODULE_ID index, uint16_t address, uint32_t *rxd) { uint8_t i; uint32_t x; uint16_t spiTransferSize = 6; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); for (i = 2; i < 6; i++) { spiReceiveBuffer[i] = spi_readwrite(0x00); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); // Update data *rxd = 0; for (i = 2; i < 6; i++) { x = (uint32_t) spiReceiveBuffer[i]; *rxd += x << ((i - 2)*8); } return spiTransferError; } int8_t DRV_CANFDSPI_WriteWord(CANFDSPI_MODULE_ID index, uint16_t address, uint32_t txd) { uint8_t i; uint16_t spiTransferSize = 6; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); // Split word into 4 bytes and add them to buffer for (i = 0; i < 4; i++) { spiTransmitBuffer[i + 2] = (uint8_t) ((txd >> (i * 8)) & 0xFF); } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); spi_readwrite(spiTransmitBuffer[3]); spi_readwrite(spiTransmitBuffer[4]); spi_readwrite(spiTransmitBuffer[5]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_ReadHalfWord(CANFDSPI_MODULE_ID index, uint16_t address, uint16_t *rxd) { uint8_t i; uint32_t x; uint16_t spiTransferSize = 4; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); for (i = 2; i < 4; i++) { spiReceiveBuffer[i] = spi_readwrite(0x00); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); // Update data *rxd = 0; for (i = 2; i < 4; i++) { x = (uint32_t) spiReceiveBuffer[i]; *rxd += x << ((i - 2)*8); } return spiTransferError; } int8_t DRV_CANFDSPI_WriteHalfWord(CANFDSPI_MODULE_ID index, uint16_t address, uint16_t txd) { uint8_t i; uint16_t spiTransferSize = 4; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); // Split word into 2 bytes and add them to buffer for (i = 0; i < 2; i++) { spiTransmitBuffer[i + 2] = (uint8_t) ((txd >> (i * 8)) & 0xFF); } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); spi_readwrite(spiTransmitBuffer[3]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_WriteByteSafe(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t txd) { uint16_t crcResult = 0; uint16_t spiTransferSize = 5; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE_SAFE << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); spiTransmitBuffer[2] = txd; // Add CRC crcResult = DRV_CANFDSPI_CalculateCRC16(spiTransmitBuffer, 3); spiTransmitBuffer[3] = (crcResult >> 8) & 0xFF; spiTransmitBuffer[4] = crcResult & 0xFF; #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); spi_readwrite(spiTransmitBuffer[3]); spi_readwrite(spiTransmitBuffer[4]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_WriteWordSafe(CANFDSPI_MODULE_ID index, uint16_t address, uint32_t txd) { uint8_t i; uint16_t crcResult = 0; uint16_t spiTransferSize = 8; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE_SAFE << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); // Split word into 4 bytes and add them to buffer for (i = 0; i < 4; i++) { spiTransmitBuffer[i + 2] = (uint8_t) ((txd >> (i * 8)) & 0xFF); } // Add CRC crcResult = DRV_CANFDSPI_CalculateCRC16(spiTransmitBuffer, 6); spiTransmitBuffer[6] = (crcResult >> 8) & 0xFF; spiTransmitBuffer[7] = crcResult & 0xFF; #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); spi_readwrite(spiTransmitBuffer[3]); spi_readwrite(spiTransmitBuffer[4]); spi_readwrite(spiTransmitBuffer[5]); spi_readwrite(spiTransmitBuffer[6]); spi_readwrite(spiTransmitBuffer[7]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_ReadByteArray(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t *rxd, uint16_t nBytes) { uint16_t i; uint16_t spiTransferSize = nBytes + 2; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); // Clear data for (i = 2; i < spiTransferSize; i++) { spiTransmitBuffer[i] = 0; } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); for (i = 0; i < nBytes; i++) { spiReceiveBuffer[i + 2] = spi_readwrite(0x00); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); // Update data for (i = 0; i < nBytes; i++) { rxd[i] = spiReceiveBuffer[i + 2]; } return spiTransferError; } int8_t DRV_CANFDSPI_ReadByteArrayWithCRC(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t *rxd, uint16_t nBytes, bool fromRam, bool* crcIsCorrect) { uint8_t i; uint16_t crcFromSpiSlave = 0; uint16_t crcAtController = 0; uint16_t spiTransferSize = nBytes + 5; //first two bytes for sending command & address, third for size, last two bytes for CRC int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_READ_CRC << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); if (fromRam) { spiTransmitBuffer[2] = nBytes >> 2; } else { spiTransmitBuffer[2] = nBytes; } // Clear data for (i = 3; i < spiTransferSize; i++) { spiTransmitBuffer[i] = 0; } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); for (i = 3; i < spiTransferSize; i++) { spiReceiveBuffer[i] = spi_readwrite(0x00); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); // Get CRC from controller crcFromSpiSlave = (uint16_t) (spiReceiveBuffer[spiTransferSize - 2] << 8) + (uint16_t) (spiReceiveBuffer[spiTransferSize - 1]); // Use the receive buffer to calculate CRC // First three bytes need to be command spiReceiveBuffer[0] = spiTransmitBuffer[0]; spiReceiveBuffer[1] = spiTransmitBuffer[1]; spiReceiveBuffer[2] = spiTransmitBuffer[2]; crcAtController = DRV_CANFDSPI_CalculateCRC16(spiReceiveBuffer, nBytes + 3); // Compare CRC readings if (crcFromSpiSlave == crcAtController) { *crcIsCorrect = true; } else { *crcIsCorrect = false; } // Update data for (i = 0; i < nBytes; i++) { rxd[i] = spiReceiveBuffer[i + 3]; } return spiTransferError; } int8_t DRV_CANFDSPI_WriteByteArray(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t *txd, uint16_t nBytes) { uint16_t i; uint16_t spiTransferSize = nBytes + 2; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); // Add data for (i = 2; i < spiTransferSize; i++) { spiTransmitBuffer[i] = txd[i - 2]; } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); for (i = 2; i < spiTransferSize; i++) { spi_readwrite(spiTransmitBuffer[i]); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_WriteByteArrayWithCRC(CANFDSPI_MODULE_ID index, uint16_t address, uint8_t *txd, uint16_t nBytes, bool fromRam) { uint16_t i; uint16_t crcResult = 0; uint16_t spiTransferSize = nBytes + 5; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (uint8_t) ((cINSTRUCTION_WRITE_CRC << 4) + ((address >> 8) & 0xF)); spiTransmitBuffer[1] = (uint8_t) (address & 0xFF); if (fromRam) { spiTransmitBuffer[2] = nBytes >> 2; } else { spiTransmitBuffer[2] = nBytes; } // Add data for (i = 0; i < nBytes; i++) { spiTransmitBuffer[i + 3] = txd[i]; } // Add CRC crcResult = DRV_CANFDSPI_CalculateCRC16(spiTransmitBuffer, spiTransferSize - 2); spiTransmitBuffer[spiTransferSize - 2] = (uint8_t) ((crcResult >> 8) & 0xFF); spiTransmitBuffer[spiTransferSize - 1] = (uint8_t) (crcResult & 0xFF); #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); spi_readwrite(spiTransmitBuffer[2]); for (i = 0; i < nBytes; i++) { spi_readwrite(spiTransmitBuffer[i + 3]); } spi_readwrite(spiTransmitBuffer[spiTransferSize - 2]); spi_readwrite(spiTransmitBuffer[spiTransferSize - 1]); MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } int8_t DRV_CANFDSPI_ReadWordArray(CANFDSPI_MODULE_ID index, uint16_t address, uint32_t *rxd, uint16_t nWords) { uint16_t i, j, n; REG_t w; uint16_t spiTransferSize = nWords * 4 + 2; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (cINSTRUCTION_READ << 4) + ((address >> 8) & 0xF); spiTransmitBuffer[1] = address & 0xFF; // Clear data for (i = 2; i < spiTransferSize; i++) { spiTransmitBuffer[i] = 0; } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); for (i = 2; i < spiTransferSize; i++) { //for (i = 2; i < 6; i++) { spiReceiveBuffer[i] = spi_readwrite(0x00); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); // Convert Byte array to Word array n = 2; for (i = 0; i < nWords; i++) { w.word = 0; for (j = 0; j < 4; j++, n++) { w.byte[j] = spiReceiveBuffer[n]; } rxd[i] = w.word; } return spiTransferError; } int8_t DRV_CANFDSPI_WriteWordArray(CANFDSPI_MODULE_ID index, uint16_t address, uint32_t *txd, uint16_t nWords) { uint16_t i, j, n; REG_t w; uint16_t spiTransferSize = nWords * 4 + 2; int8_t spiTransferError = 0; // Compose command spiTransmitBuffer[0] = (cINSTRUCTION_WRITE << 4) + ((address >> 8) & 0xF); spiTransmitBuffer[1] = address & 0xFF; // Convert ByteArray to word array n = 2; for (i = 0; i < nWords; i++) { w.word = txd[i]; for (j = 0; j < 4; j++, n++) { spiTransmitBuffer[n] = w.byte[j]; } } #ifdef SPI_HAS_TRANSACTION SPI_BEGIN(); #endif MCP2518fd_SELECT(); spi_readwrite(spiTransmitBuffer[0]); spi_readwrite(spiTransmitBuffer[1]); for (i = 2; i < spiTransferSize; i++) { spi_readwrite(spiTransmitBuffer[i]); } MCP2518fd_UNSELECT(); #ifdef SPI_HAS_TRANSACTION SPI_END(); #endif delay(10); return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Configuration int8_t DRV_CANFDSPI_Configure(CANFDSPI_MODULE_ID index, CAN_CONFIG* config) { REG_CiCON ciCon; int8_t spiTransferError = 0; ciCon.word = canControlResetValues[cREGADDR_CiCON / 4]; ciCon.bF.DNetFilterCount = config->DNetFilterCount; ciCon.bF.IsoCrcEnable = config->IsoCrcEnable; ciCon.bF.ProtocolExceptionEventDisable = config->ProtocolExpectionEventDisable; ciCon.bF.WakeUpFilterEnable = config->WakeUpFilterEnable; ciCon.bF.WakeUpFilterTime = config->WakeUpFilterTime; ciCon.bF.BitRateSwitchDisable = config->BitRateSwitchDisable; ciCon.bF.RestrictReTxAttempts = config->RestrictReTxAttempts; ciCon.bF.EsiInGatewayMode = config->EsiInGatewayMode; ciCon.bF.SystemErrorToListenOnly = config->SystemErrorToListenOnly; ciCon.bF.StoreInTEF = config->StoreInTEF; ciCon.bF.TXQEnable = config->TXQEnable; ciCon.bF.TxBandWidthSharing = config->TxBandWidthSharing; spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiCON, ciCon.word); if (spiTransferError) { return -1; } return spiTransferError; } int8_t DRV_CANFDSPI_ConfigureObjectReset(CAN_CONFIG* config) { REG_CiCON ciCon; ciCon.word = canControlResetValues[cREGADDR_CiCON / 4]; config->DNetFilterCount = ciCon.bF.DNetFilterCount; config->IsoCrcEnable = ciCon.bF.IsoCrcEnable; config->ProtocolExpectionEventDisable = ciCon.bF.ProtocolExceptionEventDisable; config->WakeUpFilterEnable = ciCon.bF.WakeUpFilterEnable; config->WakeUpFilterTime = ciCon.bF.WakeUpFilterTime; config->BitRateSwitchDisable = ciCon.bF.BitRateSwitchDisable; config->RestrictReTxAttempts = ciCon.bF.RestrictReTxAttempts; config->EsiInGatewayMode = ciCon.bF.EsiInGatewayMode; config->SystemErrorToListenOnly = ciCon.bF.SystemErrorToListenOnly; config->StoreInTEF = ciCon.bF.StoreInTEF; config->TXQEnable = ciCon.bF.TXQEnable; config->TxBandWidthSharing = ciCon.bF.TxBandWidthSharing; return 0; } // ***************************************************************************** // ***************************************************************************** // Section: Operating mode int8_t DRV_CANFDSPI_OperationModeSelect(CANFDSPI_MODULE_ID index, CAN_OPERATION_MODE opMode) { uint8_t d = 0; int8_t spiTransferError = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON + 3, &d); if (spiTransferError) { return -1; } // Modify d &= ~0x07; d |= opMode; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiCON + 3, d); if (spiTransferError) { return -2; } return spiTransferError; } CAN_OPERATION_MODE DRV_CANFDSPI_OperationModeGet(CANFDSPI_MODULE_ID index) { uint8_t d = 0; CAN_OPERATION_MODE mode = CAN_INVALID_MODE; int8_t spiTransferError = 0; // Read Opmode spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON + 2, &d); if (spiTransferError) { return CAN_INVALID_MODE; } // Get Opmode bits d = (d >> 5) & 0x7; // Decode Opmode switch (d) { case CAN_NORMAL_MODE: mode = CAN_NORMAL_MODE; break; case CAN_SLEEP_MODE: mode = CAN_SLEEP_MODE; break; case CAN_INTERNAL_LOOPBACK_MODE: mode = CAN_INTERNAL_LOOPBACK_MODE; break; case CAN_EXTERNAL_LOOPBACK_MODE: mode = CAN_EXTERNAL_LOOPBACK_MODE; break; case CAN_LISTEN_ONLY_MODE: mode = CAN_LISTEN_ONLY_MODE; break; case CAN_CONFIGURATION_MODE: mode = CAN_CONFIGURATION_MODE; break; case CAN_CLASSIC_MODE: mode = CAN_CLASSIC_MODE; break; case CAN_RESTRICTED_MODE: mode = CAN_RESTRICTED_MODE; break; default: mode = CAN_INVALID_MODE; break; } return mode; } int8_t DRV_CANFDSPI_LowPowerModeEnable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; #ifdef MCP2517FD // LPM not implemented spiTransferError = -100; #else // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC, &d); if (spiTransferError) { return -1; } // Modify d |= 0x08; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, d); if (spiTransferError) { return -2; } #endif return spiTransferError; } int8_t DRV_CANFDSPI_LowPowerModeDisable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; #ifdef MCP2517FD // LPM not implemented spiTransferError = -100; #else // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC, &d); if (spiTransferError) { return -1; } // Modify d &= ~0x08; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, d); if (spiTransferError) { return -2; } #endif return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: CAN Transmit int8_t DRV_CANFDSPI_TransmitChannelConfigure(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_CONFIG* config) { int8_t spiTransferError = 0; uint16_t a = 0; Serial.printf("into DRV_CANFDSPI_TransmitChannelConfigure\n\r"); // Setup FIFO REG_CiFIFOCON ciFifoCon; ciFifoCon.word = canFifoResetValues[0]; ciFifoCon.txBF.TxEnable = 1; ciFifoCon.txBF.FifoSize = config->FifoSize; ciFifoCon.txBF.PayLoadSize = config->PayLoadSize; ciFifoCon.txBF.TxAttempts = config->TxAttempts; ciFifoCon.txBF.TxPriority = config->TxPriority; ciFifoCon.txBF.RTREnable = config->RTREnable; a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_WriteWord(index, a, ciFifoCon.word); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelConfigureObjectReset(CAN_TX_FIFO_CONFIG* config) { REG_CiFIFOCON ciFifoCon; ciFifoCon.word = canFifoResetValues[0]; //10010010100101010000 config->RTREnable = ciFifoCon.txBF.RTREnable; config->TxPriority = ciFifoCon.txBF.TxPriority; config->TxAttempts = ciFifoCon.txBF.TxAttempts; config->FifoSize = ciFifoCon.txBF.FifoSize; config->PayLoadSize = ciFifoCon.txBF.PayLoadSize; return 0; } int8_t DRV_CANFDSPI_TransmitQueueConfigure(CANFDSPI_MODULE_ID index, CAN_TX_QUEUE_CONFIG* config) { int8_t spiTransferError = 0; uint16_t a = 0; // Setup FIFO REG_CiTXQCON ciFifoCon; ciFifoCon.word = canFifoResetValues[0]; ciFifoCon.txBF.TxEnable = 1; ciFifoCon.txBF.FifoSize = config->FifoSize; ciFifoCon.txBF.PayLoadSize = config->PayLoadSize; ciFifoCon.txBF.TxAttempts = config->TxAttempts; ciFifoCon.txBF.TxPriority = config->TxPriority; a = cREGADDR_CiTXQCON; spiTransferError = DRV_CANFDSPI_WriteWord(index, a, ciFifoCon.word); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitQueueConfigureObjectReset(CAN_TX_QUEUE_CONFIG* config) { REG_CiFIFOCON ciFifoCon; ciFifoCon.word = canFifoResetValues[0]; config->TxPriority = ciFifoCon.txBF.TxPriority; config->TxAttempts = ciFifoCon.txBF.TxAttempts; config->FifoSize = ciFifoCon.txBF.FifoSize; config->PayLoadSize = ciFifoCon.txBF.PayLoadSize; return 0; } int8_t DRV_CANFDSPI_TransmitChannelLoad(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_TX_MSGOBJ* txObj, uint8_t *txd, uint32_t txdNumBytes, bool flush) { Serial.printf("into DRV_CANFDSPI_TransmitChannelLoad\n\r"); uint16_t a; uint32_t fifoReg[3]; uint32_t dataBytesInObject; REG_CiFIFOCON ciFifoCon; REG_CiFIFOSTA ciFifoSta; REG_CiFIFOUA ciFifoUa; int8_t spiTransferError = 0; // Get FIFO registers a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 3); if (spiTransferError) { return -1; } // Check that it is a transmit buffer ciFifoCon.word = fifoReg[0]; if (!ciFifoCon.txBF.TxEnable) { return -2; } // Check that DLC is big enough for data dataBytesInObject = DRV_CANFDSPI_DlcToDataBytes((CAN_DLC) txObj->bF.ctrl.DLC); if (dataBytesInObject < txdNumBytes) { return -3; } // Get status ciFifoSta.word = fifoReg[1]; // Get address ciFifoUa.word = fifoReg[2]; #ifdef USERADDRESS_TIMES_FOUR a = 4 * ciFifoUa.bF.UserAddress; #else a = ciFifoUa.bF.UserAddress; #endif a += cRAMADDR_START; uint8_t txBuffer[MAX_MSG_SIZE]; txBuffer[0] = txObj->byte[0]; //not using 'for' to reduce no of instructions txBuffer[1] = txObj->byte[1]; txBuffer[2] = txObj->byte[2]; txBuffer[3] = txObj->byte[3]; txBuffer[4] = txObj->byte[4]; txBuffer[5] = txObj->byte[5]; txBuffer[6] = txObj->byte[6]; txBuffer[7] = txObj->byte[7]; uint8_t i; for (i = 0; i < txdNumBytes; i++) { txBuffer[i + 8] = txd[i]; } // Make sure we write a multiple of 4 bytes to RAM uint16_t n = 0; uint8_t j = 0; if (txdNumBytes % 4) { // Need to add bytes n = 4 - (txdNumBytes % 4); i = txdNumBytes + 8; for (j = 0; j < n; j++) { txBuffer[i + 8 + j] = 0; } } Serial.printf("txBuffer[8] = %d\n\r",txBuffer[8]); Serial.printf("txBuffer[9] = %d\n\r",txBuffer[9]); Serial.printf("txBuffer[10] = %d\n\r",txBuffer[10]); Serial.printf("txBuffer[11] = %d\n\r",txBuffer[11]); Serial.printf("txBuffer[12] = %d\n\r",txBuffer[12]); Serial.printf("txBuffer[13] = %d\n\r",txBuffer[13]); Serial.printf("txBuffer[14] = %d\n\r",txBuffer[14]); Serial.printf("txBuffer[15] = %d\n\r",txBuffer[15]); spiTransferError = DRV_CANFDSPI_WriteByteArray(index, a, txBuffer, txdNumBytes + 8 + n); if (spiTransferError) { return -4; } // Set UINC and TXREQ spiTransferError = DRV_CANFDSPI_TransmitChannelUpdate(index, channel, flush); if (spiTransferError) { return -5; } Serial.printf("end DRV_CANFDSPI_TransmitChannelLoad\n\r"); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelFlush(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { uint8_t d = 0; uint16_t a = 0; int8_t spiTransferError = 0; // Address of TXREQ a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); a += 1; // Set TXREQ d = 0x02; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, d); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelStatusGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_STATUS* status) { uint16_t a = 0; uint32_t sta = 0; uint32_t fifoReg[2]; REG_CiFIFOSTA ciFifoSta; REG_CiFIFOCON ciFifoCon; int8_t spiTransferError = 0; // Get FIFO registers a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 2); if (spiTransferError) { return -1; } // Update data ciFifoCon.word = fifoReg[0]; ciFifoSta.word = fifoReg[1]; // Update status sta = ciFifoSta.byte[0]; if (ciFifoCon.txBF.TxRequest) { sta |= CAN_TX_FIFO_TRANSMITTING; } *status = (CAN_TX_FIFO_STATUS) (sta & CAN_TX_FIFO_STATUS_MASK); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelReset(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { return DRV_CANFDSPI_ReceiveChannelReset(index, channel); } int8_t DRV_CANFDSPI_TransmitChannelUpdate(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, bool flush) { uint16_t a; REG_CiFIFOCON ciFifoCon; int8_t spiTransferError = 0; // Set UINC a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET) + 1; // Byte that contains FRESET ciFifoCon.word = 0; ciFifoCon.txBF.UINC = 1; // Set TXREQ if (flush) { ciFifoCon.txBF.TxRequest = 1; } spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[1]); if (spiTransferError) { return -1; } return spiTransferError; } int8_t DRV_CANFDSPI_TransmitRequestSet(CANFDSPI_MODULE_ID index, CAN_TXREQ_CHANNEL txreq) { int8_t spiTransferError = 0; // Write TXREQ register uint32_t w = txreq; spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTXREQ, w); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitRequestGet(CANFDSPI_MODULE_ID index, uint32_t* txreq) { int8_t spiTransferError = 0; spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTXREQ, txreq); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelAbort(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { uint16_t a; uint8_t d; int8_t spiTransferError = 0; // Address a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); a += 1; // byte address of TXREQ // Clear TXREQ d = 0x00; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, d); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitAbortAll(CANFDSPI_MODULE_ID index) { uint8_t d; int8_t spiTransferError = 0; // Read CiCON byte 3 spiTransferError = DRV_CANFDSPI_ReadByte(index, (cREGADDR_CiCON + 3), &d); if (spiTransferError) { return -1; } // Modify d |= 0x8; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, (cREGADDR_CiCON + 3), d); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TransmitBandWidthSharingSet(CANFDSPI_MODULE_ID index, CAN_TX_BANDWITH_SHARING txbws) { uint8_t d = 0; int8_t spiTransferError = 0; // Read CiCON byte 3 spiTransferError = DRV_CANFDSPI_ReadByte(index, (cREGADDR_CiCON + 3), &d); if (spiTransferError) { return -1; } // Modify d &= 0x0f; d |= (txbws << 4); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, (cREGADDR_CiCON + 3), d); if (spiTransferError) { return -2; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: CAN Receive int8_t DRV_CANFDSPI_FilterObjectConfigure(CANFDSPI_MODULE_ID index, CAN_FILTER filter, CAN_FILTEROBJ_ID* id) { uint16_t a; REG_CiFLTOBJ fObj; int8_t spiTransferError = 0; // Setup fObj.word = 0; fObj.bF = *id; a = cREGADDR_CiFLTOBJ + (filter * CiFILTER_OFFSET); spiTransferError = DRV_CANFDSPI_WriteWord(index, a, fObj.word); return spiTransferError; } int8_t DRV_CANFDSPI_FilterMaskConfigure(CANFDSPI_MODULE_ID index, CAN_FILTER filter, CAN_MASKOBJ_ID* mask) { uint16_t a; REG_CiMASK mObj; int8_t spiTransferError = 0; // Setup mObj.word = 0; mObj.bF = *mask; a = cREGADDR_CiMASK + (filter * CiFILTER_OFFSET); spiTransferError = DRV_CANFDSPI_WriteWord(index, a, mObj.word); return spiTransferError; } int8_t DRV_CANFDSPI_FilterToFifoLink(CANFDSPI_MODULE_ID index, CAN_FILTER filter, CAN_FIFO_CHANNEL channel, bool enable) { uint16_t a; REG_CiFLTCON_BYTE fCtrl; int8_t spiTransferError = 0; // Enable if (enable) { fCtrl.bF.Enable = 1; } else { fCtrl.bF.Enable = 0; } // Link fCtrl.bF.BufferPointer = channel; a = cREGADDR_CiFLTCON + filter; spiTransferError = DRV_CANFDSPI_WriteByte(index, a, fCtrl.byte); return spiTransferError; } int8_t DRV_CANFDSPI_FilterEnable(CANFDSPI_MODULE_ID index, CAN_FILTER filter) { uint16_t a; REG_CiFLTCON_BYTE fCtrl; int8_t spiTransferError = 0; // Read a = cREGADDR_CiFLTCON + filter; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &fCtrl.byte); if (spiTransferError) { return -1; } // Modify fCtrl.bF.Enable = 1; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, fCtrl.byte); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_FilterDisable(CANFDSPI_MODULE_ID index, CAN_FILTER filter) { uint16_t a; REG_CiFLTCON_BYTE fCtrl; int8_t spiTransferError = 0; // Read a = cREGADDR_CiFLTCON + filter; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &fCtrl.byte); if (spiTransferError) { return -1; } // Modify fCtrl.bF.Enable = 0; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, fCtrl.byte); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_DeviceNetFilterCountSet(CANFDSPI_MODULE_ID index, CAN_DNET_FILTER_SIZE dnfc) { uint8_t d = 0; int8_t spiTransferError = 0; // Read CiCON byte 0 spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiCON, &d); if (spiTransferError) { return -1; } // Modify d &= 0x1f; d |= dnfc; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiCON, d); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelConfigure(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_CONFIG* config) { int8_t spiTransferError = 0; uint16_t a = 0; if (channel == CAN_TXQUEUE_CH0) { return -100; } // Setup FIFO REG_CiFIFOCON ciFifoCon; ciFifoCon.word = canFifoResetValues[0]; ciFifoCon.rxBF.TxEnable = 0; ciFifoCon.rxBF.FifoSize = config->FifoSize; ciFifoCon.rxBF.PayLoadSize = config->PayLoadSize; ciFifoCon.rxBF.RxTimeStampEnable = config->RxTimeStampEnable; a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_WriteWord(index, a, ciFifoCon.word); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelConfigureObjectReset(CAN_RX_FIFO_CONFIG* config) { REG_CiFIFOCON ciFifoCon; ciFifoCon.word = canFifoResetValues[0]; config->FifoSize = ciFifoCon.rxBF.FifoSize; config->PayLoadSize = ciFifoCon.rxBF.PayLoadSize; config->RxTimeStampEnable = ciFifoCon.rxBF.RxTimeStampEnable; return 0; } int8_t DRV_CANFDSPI_ReceiveChannelStatusGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_STATUS* status) { uint16_t a; REG_CiFIFOSTA ciFifoSta; int8_t spiTransferError = 0; // Read ciFifoSta.word = 0; a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); if (spiTransferError) { return -1; } // Update data *status = (CAN_RX_FIFO_STATUS) (ciFifoSta.byte[0] & 0x0F); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveMessageGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_RX_MSGOBJ* rxObj, uint8_t *rxd, uint8_t nBytes) { uint8_t n = 0; uint8_t i = 0; uint16_t a; uint32_t fifoReg[3]; REG_CiFIFOCON ciFifoCon; REG_CiFIFOSTA ciFifoSta; REG_CiFIFOUA ciFifoUa; int8_t spiTransferError = 0; // Get FIFO registers a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 3); if (spiTransferError) { return -1; } Serial.printf("ciFifoCon.txBF.TxEnable2 = %d\n\r",ciFifoCon.txBF.TxEnable); // Check that it is a receive buffer ciFifoCon.word = fifoReg[0]; Serial.printf("ciFifoCon.txBF.TxEnable3 = %d\n\r",fifoReg[0]); ciFifoCon.txBF.TxEnable = 0; if (ciFifoCon.txBF.TxEnable) { return -2; } // Get Status ciFifoSta.word = fifoReg[1]; // Get address ciFifoUa.word = fifoReg[2]; #ifdef USERADDRESS_TIMES_FOUR a = 4 * ciFifoUa.bF.UserAddress; #else a = ciFifoUa.bF.UserAddress; #endif a += cRAMADDR_START; // Number of bytes to read n = nBytes + 8; // Add 8 header bytes if (ciFifoCon.rxBF.RxTimeStampEnable) { n += 4; // Add 4 time stamp bytes } // Make sure we read a multiple of 4 bytes from RAM if (n % 4) { n = n + 4 - (n % 4); } // Read rxObj using one access uint8_t ba[MAX_MSG_SIZE]; if (n > MAX_MSG_SIZE) { n = MAX_MSG_SIZE; } spiTransferError = DRV_CANFDSPI_ReadByteArray(index, a, ba, n); if (spiTransferError) { return -3; } // Assign message header REG_t myReg; myReg.byte[0] = ba[0]; myReg.byte[1] = ba[1]; myReg.byte[2] = ba[2]; myReg.byte[3] = ba[3]; rxObj->word[0] = myReg.word; myReg.byte[0] = ba[4]; myReg.byte[1] = ba[5]; myReg.byte[2] = ba[6]; myReg.byte[3] = ba[7]; rxObj->word[1] = myReg.word; if (ciFifoCon.rxBF.RxTimeStampEnable) { myReg.byte[0] = ba[8]; myReg.byte[1] = ba[9]; myReg.byte[2] = ba[10]; myReg.byte[3] = ba[11]; rxObj->word[2] = myReg.word; // Assign message data for (i = 0; i < nBytes; i++) { rxd[i] = ba[i + 12]; } } else { rxObj->word[2] = 0; // Assign message data for (i = 0; i < nBytes; i++) { rxd[i] = ba[i + 8]; } } // UINC channel spiTransferError = DRV_CANFDSPI_ReceiveChannelUpdate(index, channel); if (spiTransferError) { return -4; } Serial.printf("DRV_CANFDSPI_ReceiveMessageGet end\n\r"); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelReset(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { uint16_t a = 0; REG_CiFIFOCON ciFifoCon; int8_t spiTransferError = 0; // Address and data a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET) + 1; // Byte that contains FRESET ciFifoCon.word = 0; ciFifoCon.rxBF.FRESET = 1; spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[1]); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelUpdate(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { uint16_t a = 0; REG_CiFIFOCON ciFifoCon; int8_t spiTransferError = 0; ciFifoCon.word = 0; // Set UINC a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET) + 1; // Byte that contains FRESET ciFifoCon.rxBF.UINC = 1; // Write byte spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[1]); return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Transmit Event FIFO int8_t DRV_CANFDSPI_TefStatusGet(CANFDSPI_MODULE_ID index, CAN_TEF_FIFO_STATUS* status) { int8_t spiTransferError = 0; uint16_t a = 0; // Read REG_CiTEFSTA ciTefSta; ciTefSta.word = 0; a = cREGADDR_CiTEFSTA; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefSta.byte[0]); if (spiTransferError) { return -1; } // Update data *status = (CAN_TEF_FIFO_STATUS) (ciTefSta.byte[0] & CAN_TEF_FIFO_STATUS_MASK); return spiTransferError; } int8_t DRV_CANFDSPI_TefMessageGet(CANFDSPI_MODULE_ID index, CAN_TEF_MSGOBJ* tefObj) { int8_t spiTransferError = 0; uint16_t a = 0; uint32_t fifoReg[3]; uint8_t n = 0; // Get FIFO registers a = cREGADDR_CiTEFCON; spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, fifoReg, 3); if (spiTransferError) { return -1; } // Get control REG_CiTEFCON ciTefCon; ciTefCon.word = fifoReg[0]; // Get status REG_CiTEFSTA ciTefSta; ciTefSta.word = fifoReg[1]; // Get address REG_CiFIFOUA ciTefUa; ciTefUa.word = fifoReg[2]; #ifdef USERADDRESS_TIMES_FOUR a = 4 * ciTefUa.bF.UserAddress; #else a = ciTefUa.bF.UserAddress; #endif a += cRAMADDR_START; // Number of bytes to read n = 8; // 8 header bytes if (ciTefCon.bF.TimeStampEnable) { n += 4; // Add 4 time stamp bytes } // Read rxObj using one access uint8_t ba[12]; spiTransferError = DRV_CANFDSPI_ReadByteArray(index, a, ba, n); if (spiTransferError) { return -2; } // Assign message header REG_t myReg; myReg.byte[0] = ba[0]; myReg.byte[1] = ba[1]; myReg.byte[2] = ba[2]; myReg.byte[3] = ba[3]; tefObj->word[0] = myReg.word; myReg.byte[0] = ba[4]; myReg.byte[1] = ba[5]; myReg.byte[2] = ba[6]; myReg.byte[3] = ba[7]; tefObj->word[1] = myReg.word; if (ciTefCon.bF.TimeStampEnable) { myReg.byte[0] = ba[8]; myReg.byte[1] = ba[9]; myReg.byte[2] = ba[10]; myReg.byte[3] = ba[11]; tefObj->word[2] = myReg.word; } else { tefObj->word[2] = 0; } // Set UINC spiTransferError = DRV_CANFDSPI_TefUpdate(index); if (spiTransferError) { return -3; } return spiTransferError; } int8_t DRV_CANFDSPI_TefReset(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint16_t a = 0; // Set FRESET a = cREGADDR_CiTEFCON + 1; REG_CiTEFCON ciTefCon; ciTefCon.word = 0; ciTefCon.bF.FRESET = 1; // Write byte spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[1]); return spiTransferError; } int8_t DRV_CANFDSPI_TefUpdate(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint16_t a = 0; // Set UINC a = cREGADDR_CiTEFCON + 1; REG_CiTEFCON ciTefCon; ciTefCon.word = 0; ciTefCon.bF.UINC = 1; // Write byte spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[1]); return spiTransferError; } int8_t DRV_CANFDSPI_TefConfigure(CANFDSPI_MODULE_ID index, CAN_TEF_CONFIG* config) { int8_t spiTransferError = 0; // Setup FIFO REG_CiTEFCON ciTefCon; ciTefCon.word = canControlResetValues[cREGADDR_CiTEFCON / 4]; ciTefCon.bF.FifoSize = config->FifoSize; ciTefCon.bF.TimeStampEnable = config->TimeStampEnable; spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTEFCON, ciTefCon.word); return spiTransferError; } int8_t DRV_CANFDSPI_TefConfigureObjectReset(CAN_TEF_CONFIG* config) { REG_CiTEFCON ciTefCon; ciTefCon.word = canFifoResetValues[0]; config->FifoSize = ciTefCon.bF.FifoSize; config->TimeStampEnable = ciTefCon.bF.TimeStampEnable; return 0; } // ***************************************************************************** // ***************************************************************************** // Section: Module Events int8_t DRV_CANFDSPI_ModuleEventGet(CANFDSPI_MODULE_ID index, CAN_MODULE_EVENT* flags) { int8_t spiTransferError = 0; // Read Interrupt flags REG_CiINTFLAG intFlags; intFlags.word = 0; spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, cREGADDR_CiINTFLAG, &intFlags.word); if (spiTransferError) { return -1; } // Update data *flags = (CAN_MODULE_EVENT) (intFlags.word & CAN_ALL_EVENTS); return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventEnable(CANFDSPI_MODULE_ID index, CAN_MODULE_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiINTENABLE; REG_CiINTENABLE intEnables; intEnables.word = 0; spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, a, &intEnables.word); if (spiTransferError) { return -1; } // Modify intEnables.word |= (flags & CAN_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, a, intEnables.word); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventDisable(CANFDSPI_MODULE_ID index, CAN_MODULE_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiINTENABLE; REG_CiINTENABLE intEnables; intEnables.word = 0; spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, a, &intEnables.word); if (spiTransferError) { return -1; } // Modify intEnables.word &= ~(flags & CAN_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, a, intEnables.word); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventClear(CANFDSPI_MODULE_ID index, CAN_MODULE_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt flags a = cREGADDR_CiINTFLAG; REG_CiINTFLAG intFlags; intFlags.word = 0; // Write 1 to all flags except the ones that we want to clear // Writing a 1 will not set the flag // Only writing a 0 will clear it // The flags are HS/C intFlags.word = CAN_ALL_EVENTS; intFlags.word &= ~flags; // Write spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, a, intFlags.word); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventRxCodeGet(CANFDSPI_MODULE_ID index, CAN_RXCODE* rxCode) { int8_t spiTransferError = 0; uint16_t a = 0; uint8_t rxCodeByte = 0; // Read a = cREGADDR_CiVEC + 3; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &rxCodeByte); if (spiTransferError) { return -1; } // Decode data // 0x40 = "no interrupt" (CAN_FIFO_CIVEC_NOINTERRUPT) if ((rxCodeByte < CAN_RXCODE_TOTAL_CHANNELS) || (rxCodeByte == CAN_RXCODE_NO_INT)) { *rxCode = (CAN_RXCODE) rxCodeByte; } else { *rxCode = CAN_RXCODE_RESERVED; // shouldn't get here } return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventTxCodeGet(CANFDSPI_MODULE_ID index, CAN_TXCODE* txCode) { int8_t spiTransferError = 0; uint16_t a = 0; uint8_t txCodeByte = 0; // Read a = cREGADDR_CiVEC + 2; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &txCodeByte); if (spiTransferError) { return -1; } // Decode data // 0x40 = "no interrupt" (CAN_FIFO_CIVEC_NOINTERRUPT) if ((txCodeByte < CAN_TXCODE_TOTAL_CHANNELS) || (txCodeByte == CAN_TXCODE_NO_INT)) { *txCode = (CAN_TXCODE) txCodeByte; } else { *txCode = CAN_TXCODE_RESERVED; // shouldn't get here } return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventFilterHitGet(CANFDSPI_MODULE_ID index, CAN_FILTER* filterHit) { int8_t spiTransferError = 0; uint16_t a = 0; uint8_t filterHitByte = 0; // Read a = cREGADDR_CiVEC + 1; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &filterHitByte); if (spiTransferError) { return -1; } // Update data *filterHit = (CAN_FILTER) filterHitByte; return spiTransferError; } int8_t DRV_CANFDSPI_ModuleEventIcodeGet(CANFDSPI_MODULE_ID index, CAN_ICODE* icode) { int8_t spiTransferError = 0; uint16_t a = 0; uint8_t icodeByte = 0; // Read a = cREGADDR_CiVEC; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &icodeByte); if (spiTransferError) { return -1; } // Decode if ((icodeByte < CAN_ICODE_RESERVED) && ((icodeByte < CAN_ICODE_TOTAL_CHANNELS) || (icodeByte >= CAN_ICODE_NO_INT))) { *icode = (CAN_ICODE) icodeByte; } else { *icode = CAN_ICODE_RESERVED; // shouldn't get here } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Transmit FIFO Events int8_t DRV_CANFDSPI_TransmitChannelEventGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT* flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt flags REG_CiFIFOSTA ciFifoSta; ciFifoSta.word = 0; a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); if (spiTransferError) { return -1; } // Update data *flags = (CAN_TX_FIFO_EVENT) (ciFifoSta.byte[0] & CAN_TX_FIFO_ALL_EVENTS); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitEventGet(CANFDSPI_MODULE_ID index, uint32_t* txif) { int8_t spiTransferError = 0; spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTXIF, txif); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitEventAttemptGet(CANFDSPI_MODULE_ID index, uint32_t* txatif) { int8_t spiTransferError = 0; spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTXATIF, txatif); return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelIndexGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, uint8_t* idx) { int8_t spiTransferError = 0; uint16_t a = 0; // Read index REG_CiFIFOSTA ciFifoSta; ciFifoSta.word = 0; a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadWord(index, a, &ciFifoSta.word); if (spiTransferError) { return -1; } // Update data *idx = ciFifoSta.txBF.FifoIndex; return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelEventEnable(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); REG_CiFIFOCON ciFifoCon; ciFifoCon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); if (spiTransferError) { return -1; } // Modify ciFifoCon.byte[0] |= (flags & CAN_TX_FIFO_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelEventDisable(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_TX_FIFO_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); REG_CiFIFOCON ciFifoCon; ciFifoCon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); if (spiTransferError) { return -1; } // Modify ciFifoCon.byte[0] &= ~(flags & CAN_TX_FIFO_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TransmitChannelEventAttemptClear(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); REG_CiFIFOSTA ciFifoSta; ciFifoSta.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); if (spiTransferError) { return -1; } // Modify ciFifoSta.byte[0] &= ~CAN_TX_FIFO_ATTEMPTS_EXHAUSTED_EVENT; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoSta.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Receive FIFO Events int8_t DRV_CANFDSPI_ReceiveChannelEventGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT* flags) { Serial.println("DRV_CANFDSPI_ReceiveChannelEventGet\n\r"); int8_t spiTransferError = 0; uint16_t a = 0; if (channel == CAN_TXQUEUE_CH0) return -100; // Read Interrupt flags REG_CiFIFOSTA ciFifoSta; ciFifoSta.word = 0; a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); if (spiTransferError) { return -1; } // Update data *flags = (CAN_RX_FIFO_EVENT) (ciFifoSta.byte[0] & CAN_RX_FIFO_ALL_EVENTS); Serial.printf("DRV_CANFDSPI_ReceiveChannelEventGet flags = %x\n\r",(*flags)); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveEventGet(CANFDSPI_MODULE_ID index, uint32_t* rxif) { int8_t spiTransferError = 0; spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiRXIF, rxif); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveEventOverflowGet(CANFDSPI_MODULE_ID index, uint32_t* rxovif) { int8_t spiTransferError = 0; spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiRXOVIF, rxovif); return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelIndexGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, uint8_t* idx) { return DRV_CANFDSPI_TransmitChannelIndexGet(index, channel, idx); } int8_t DRV_CANFDSPI_ReceiveChannelEventEnable(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; if (channel == CAN_TXQUEUE_CH0) return -100; // Read Interrupt Enables a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); REG_CiFIFOCON ciFifoCon; ciFifoCon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); if (spiTransferError) { return -1; } // Modify ciFifoCon.byte[0] |= (flags & CAN_RX_FIFO_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelEventDisable(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, CAN_RX_FIFO_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; if (channel == CAN_TXQUEUE_CH0) return -100; // Read Interrupt Enables a = cREGADDR_CiFIFOCON + (channel * CiFIFO_OFFSET); REG_CiFIFOCON ciFifoCon; ciFifoCon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoCon.byte[0]); if (spiTransferError) { return -1; } // Modify ciFifoCon.byte[0] &= ~(flags & CAN_RX_FIFO_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoCon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_ReceiveChannelEventOverflowClear(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel) { int8_t spiTransferError = 0; uint16_t a = 0; if (channel == CAN_TXQUEUE_CH0) return -100; // Read Interrupt Flags REG_CiFIFOSTA ciFifoSta; ciFifoSta.word = 0; a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciFifoSta.byte[0]); if (spiTransferError) { return -1; } // Modify ciFifoSta.byte[0] &= ~(CAN_RX_FIFO_OVERFLOW_EVENT); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciFifoSta.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Transmit Event FIFO Events int8_t DRV_CANFDSPI_TefEventGet(CANFDSPI_MODULE_ID index, CAN_TEF_FIFO_EVENT* flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt flags REG_CiTEFSTA ciTefSta; ciTefSta.word = 0; a = cREGADDR_CiTEFSTA; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefSta.byte[0]); if (spiTransferError) { return -1; } // Update data *flags = (CAN_TEF_FIFO_EVENT) (ciTefSta.byte[0] & CAN_TEF_FIFO_ALL_EVENTS); return spiTransferError; } int8_t DRV_CANFDSPI_TefEventEnable(CANFDSPI_MODULE_ID index, CAN_TEF_FIFO_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiTEFCON; REG_CiTEFCON ciTefCon; ciTefCon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefCon.byte[0]); if (spiTransferError) { return -1; } // Modify ciTefCon.byte[0] |= (flags & CAN_TEF_FIFO_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TefEventDisable(CANFDSPI_MODULE_ID index, CAN_TEF_FIFO_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Enables a = cREGADDR_CiTEFCON; REG_CiTEFCON ciTefCon; ciTefCon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefCon.byte[0]); if (spiTransferError) { return -1; } // Modify ciTefCon.byte[0] &= ~(flags & CAN_TEF_FIFO_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefCon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TefEventOverflowClear(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt Flags REG_CiTEFSTA ciTefSta; ciTefSta.word = 0; a = cREGADDR_CiTEFSTA; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &ciTefSta.byte[0]); if (spiTransferError) { return -1; } // Modify ciTefSta.byte[0] &= ~(CAN_TEF_FIFO_OVERFLOW_EVENT); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, ciTefSta.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Error Handling int8_t DRV_CANFDSPI_ErrorCountTransmitGet(CANFDSPI_MODULE_ID index, uint8_t* tec) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Error count a = cREGADDR_CiTREC + 1; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, tec); return spiTransferError; } int8_t DRV_CANFDSPI_ErrorCountReceiveGet(CANFDSPI_MODULE_ID index, uint8_t* rec) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Error count a = cREGADDR_CiTREC; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, rec); return spiTransferError; } int8_t DRV_CANFDSPI_ErrorStateGet(CANFDSPI_MODULE_ID index, CAN_ERROR_STATE* flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Error state a = cREGADDR_CiTREC + 2; uint8_t f = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &f); if (spiTransferError) { return -1; } // Update data *flags = (CAN_ERROR_STATE) (f & CAN_ERROR_ALL); return spiTransferError; } int8_t DRV_CANFDSPI_ErrorCountStateGet(CANFDSPI_MODULE_ID index, uint8_t* tec, uint8_t* rec, CAN_ERROR_STATE* flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Error a = cREGADDR_CiTREC; REG_CiTREC ciTrec; ciTrec.word = 0; spiTransferError = DRV_CANFDSPI_ReadWord(index, a, &ciTrec.word); if (spiTransferError) { return -1; } // Update data *tec = ciTrec.byte[1]; *rec = ciTrec.byte[0]; *flags = (CAN_ERROR_STATE) (ciTrec.byte[2] & CAN_ERROR_ALL); return spiTransferError; } int8_t DRV_CANFDSPI_BusDiagnosticsGet(CANFDSPI_MODULE_ID index, CAN_BUS_DIAGNOSTIC* bd) { int8_t spiTransferError = 0; uint16_t a = 0; // Read diagnostic registers all in one shot a = cREGADDR_CiBDIAG0; uint32_t w[2]; spiTransferError = DRV_CANFDSPI_ReadWordArray(index, a, w, 2); if (spiTransferError) { return -1; } // Update data CAN_BUS_DIAGNOSTIC b; b.word[0] = w[0]; b.word[1] = w[1] & 0x0000ffff; b.word[2] = (w[1] >> 16) & 0x0000ffff; *bd = b; return spiTransferError; } int8_t DRV_CANFDSPI_BusDiagnosticsClear(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t a = 0; // Clear diagnostic registers all in one shot a = cREGADDR_CiBDIAG0; uint32_t w[2]; w[0] = 0; w[1] = 0; spiTransferError = DRV_CANFDSPI_WriteWordArray(index, a, w, 2); return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: ECC int8_t DRV_CANFDSPI_EccEnable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_ECCCON, &d); if (spiTransferError) { return -1; } // Modify d |= 0x01; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_ECCCON, d); if (spiTransferError) { return -2; } return 0; } int8_t DRV_CANFDSPI_EccDisable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_ECCCON, &d); if (spiTransferError) { return -1; } // Modify d &= ~0x01; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_ECCCON, d); if (spiTransferError) { return -2; } return 0; } int8_t DRV_CANFDSPI_EccEventGet(CANFDSPI_MODULE_ID index, CAN_ECC_EVENT* flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Interrupt flags uint8_t eccStatus = 0; a = cREGADDR_ECCSTA; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccStatus); if (spiTransferError) { return -1; } // Update data *flags = (CAN_ECC_EVENT) (eccStatus & CAN_ECC_ALL_EVENTS); return spiTransferError; } int8_t DRV_CANFDSPI_EccParitySet(CANFDSPI_MODULE_ID index, uint8_t parity) { int8_t spiTransferError = 0; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_ECCCON + 1, parity); return spiTransferError; } int8_t DRV_CANFDSPI_EccParityGet(CANFDSPI_MODULE_ID index, uint8_t* parity) { int8_t spiTransferError = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_ECCCON + 1, parity); return spiTransferError; } int8_t DRV_CANFDSPI_EccErrorAddressGet(CANFDSPI_MODULE_ID index, uint16_t* a) { int8_t spiTransferError = 0; REG_ECCSTA reg; // Read spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_ECCSTA, ®.word); if (spiTransferError) { return -1; } // Update data *a = reg.bF.ErrorAddress; return spiTransferError; } int8_t DRV_CANFDSPI_EccEventEnable(CANFDSPI_MODULE_ID index, CAN_ECC_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_ECCCON; uint8_t eccInterrupts = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccInterrupts); if (spiTransferError) { return -1; } // Modify eccInterrupts |= (flags & CAN_ECC_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, eccInterrupts); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_EccEventDisable(CANFDSPI_MODULE_ID index, CAN_ECC_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_ECCCON; uint8_t eccInterrupts = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccInterrupts); if (spiTransferError) { return -1; } // Modify eccInterrupts &= ~(flags & CAN_ECC_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, eccInterrupts); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_EccEventClear(CANFDSPI_MODULE_ID index, CAN_ECC_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_ECCSTA; uint8_t eccStat = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &eccStat); if (spiTransferError) { return -1; } // Modify eccStat &= ~(flags & CAN_ECC_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, eccStat); if (spiTransferError) { return -2; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: CRC int8_t DRV_CANFDSPI_CrcEventEnable(CANFDSPI_MODULE_ID index, CAN_CRC_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read interrupt control bits of CRC Register a = cREGADDR_CRC + 3; uint8_t crc; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); if (spiTransferError) { return -1; } // Modify crc |= (flags & CAN_CRC_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, crc); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_CrcEventDisable(CANFDSPI_MODULE_ID index, CAN_CRC_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read interrupt control bits of CRC Register a = cREGADDR_CRC + 3; uint8_t crc; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); if (spiTransferError) { return -1; } // Modify crc &= ~(flags & CAN_CRC_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, crc); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_CrcEventClear(CANFDSPI_MODULE_ID index, CAN_CRC_EVENT flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read interrupt flags of CRC Register a = cREGADDR_CRC + 2; uint8_t crc; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); if (spiTransferError) { return -1; } // Modify crc &= ~(flags & CAN_CRC_ALL_EVENTS); // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, crc); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_CrcEventGet(CANFDSPI_MODULE_ID index, CAN_CRC_EVENT* flags) { int8_t spiTransferError = 0; uint16_t a = 0; // Read interrupt flags of CRC Register a = cREGADDR_CRC + 2; uint8_t crc; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &crc); if (spiTransferError) { return -1; } // Update data *flags = (CAN_CRC_EVENT) (crc & CAN_CRC_ALL_EVENTS); return spiTransferError; } int8_t DRV_CANFDSPI_CrcValueGet(CANFDSPI_MODULE_ID index, uint16_t* crc) { int8_t spiTransferError = 0; // Read CRC value from CRC Register spiTransferError = DRV_CANFDSPI_ReadHalfWord(index, cREGADDR_CRC, crc); return spiTransferError; } // int8_t spi_test() // { // uint8_t txd[MAX_DATA_BYTES]; // uint8_t rxd[MAX_DATA_BYTES]; // uint8_t i; // uint8_t length; // for (length = 4;length <= MAX_DATA_BYTES; length += 4) { // for (i = 0; i < length; i++) { // txd[i] = rand() & 0xff; // rxd[i] = 0xff; // } // DRV_CANFDSPI_WriteByteArray(0,cRAMADDR_START,txd,length); // DRV_CANFDSPI_ReadByteArray(0,cRAMADDR_START,rxd,length); // bool good = false; // for (i = 0; i < length;i++) { // good = txd[i] == rxd[i]; // if (!good) { // return 0; // } // } // return 1; // } // } int8_t DRV_CANFDSPI_RamInit(CANFDSPI_MODULE_ID index, uint8_t d) { // int8_t b; // b = spi_test(); uint8_t txd[SPI_DEFAULT_BUFFER_LENGTH]; uint32_t k; int8_t spiTransferError = 0; // Prepare data for (k = 0; k < SPI_DEFAULT_BUFFER_LENGTH; k++) { txd[k] = d; } uint16_t a = cRAMADDR_START; for (k = 0; k < (cRAM_SIZE / SPI_DEFAULT_BUFFER_LENGTH); k++) { spiTransferError = DRV_CANFDSPI_WriteByteArray(index, a, txd, SPI_DEFAULT_BUFFER_LENGTH); if (spiTransferError) { return -1; } a += SPI_DEFAULT_BUFFER_LENGTH; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Time Stamp int8_t DRV_CANFDSPI_TimeStampEnable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiTSCON + 2, &d); if (spiTransferError) { return -1; } // Modify d |= 0x01; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiTSCON + 2, d); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TimeStampDisable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiTSCON + 2, &d); if (spiTransferError) { return -1; } // Modify d &= 0x06; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiTSCON + 2, d); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TimeStampGet(CANFDSPI_MODULE_ID index, uint32_t* ts) { int8_t spiTransferError = 0; // Read spiTransferError = DRV_CANFDSPI_ReadWord(index, cREGADDR_CiTBC, ts); return spiTransferError; } int8_t DRV_CANFDSPI_TimeStampSet(CANFDSPI_MODULE_ID index, uint32_t ts) { int8_t spiTransferError = 0; // Write spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTBC, ts); return spiTransferError; } int8_t DRV_CANFDSPI_TimeStampModeConfigure(CANFDSPI_MODULE_ID index, CAN_TS_MODE mode) { int8_t spiTransferError = 0; uint8_t d = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_CiTSCON + 2, &d); if (spiTransferError) { return -1; } // Modify d &= 0x01; d |= mode << 1; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_CiTSCON + 2, d); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_TimeStampPrescalerSet(CANFDSPI_MODULE_ID index, uint16_t ps) { int8_t spiTransferError = 0; // Write spiTransferError = DRV_CANFDSPI_WriteHalfWord(index, cREGADDR_CiTSCON, ps); return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Oscillator and Bit Time int8_t DRV_CANFDSPI_OscillatorEnable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint8_t d = 0; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC, &d); if (spiTransferError) { return -1; } // Modify d &= ~0x4; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, d); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_OscillatorControlSet(CANFDSPI_MODULE_ID index, CAN_OSC_CTRL ctrl) { int8_t spiTransferError = 0; REG_OSC osc; osc.word = 0; osc.bF.PllEnable = ctrl.PllEnable; osc.bF.OscDisable = ctrl.OscDisable; osc.bF.SCLKDIV = ctrl.SclkDivide; osc.bF.CLKODIV = ctrl.ClkOutDivide; #ifndef MCP2517FD osc.bF.LowPowerModeEnable = ctrl.LowPowerModeEnable; #endif // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, cREGADDR_OSC, osc.byte[0]); return spiTransferError; } int8_t DRV_CANFDSPI_OscillatorControlObjectReset(CAN_OSC_CTRL* ctrl) { REG_OSC osc; osc.word = mcp25xxfdControlResetValues[0]; ctrl->PllEnable = osc.bF.PllEnable; ctrl->OscDisable = osc.bF.OscDisable; ctrl->SclkDivide = osc.bF.SCLKDIV; ctrl->ClkOutDivide = osc.bF.CLKODIV; return 0; } int8_t DRV_CANFDSPI_OscillatorStatusGet(CANFDSPI_MODULE_ID index, CAN_OSC_STATUS* status) { int8_t spiTransferError = 0; REG_OSC osc; osc.word = 0; CAN_OSC_STATUS stat; // Read spiTransferError = DRV_CANFDSPI_ReadByte(index, cREGADDR_OSC + 1, &osc.byte[1]); if (spiTransferError) { return -1; } stat.PllReady = osc.bF.PllReady; stat.OscReady = osc.bF.OscReady; stat.SclkReady = osc.bF.SclkReady; *status = stat; return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigure(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode, CAN_SYSCLK_SPEED clk) { int8_t spiTransferError = 0; // Decode clk switch (clk) { case CAN_SYSCLK_40M: spiTransferError = DRV_CANFDSPI_BitTimeConfigureNominal40MHz(index, bitTime); if (spiTransferError) return spiTransferError; spiTransferError = DRV_CANFDSPI_BitTimeConfigureData40MHz(index, bitTime, sspMode); break; case CAN_SYSCLK_20M: spiTransferError = DRV_CANFDSPI_BitTimeConfigureNominal20MHz(index, bitTime); if (spiTransferError) return spiTransferError; spiTransferError = DRV_CANFDSPI_BitTimeConfigureData20MHz(index, bitTime, sspMode); break; case CAN_SYSCLK_10M: spiTransferError = DRV_CANFDSPI_BitTimeConfigureNominal10MHz(index, bitTime); if (spiTransferError) return spiTransferError; spiTransferError = DRV_CANFDSPI_BitTimeConfigureData10MHz(index, bitTime, sspMode); break; default: spiTransferError = -1; break; } return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigureNominal40MHz(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime) { int8_t spiTransferError = 0; REG_CiNBTCFG ciNbtcfg; ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4]; // Arbitration Bit rate switch (bitTime) { // All 500K case CAN_500K_1M: case CAN_500K_2M: case CAN_500K_3M: case CAN_500K_4M: case CAN_500K_5M: case CAN_500K_6M7: case CAN_500K_8M: case CAN_500K_10M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 62; ciNbtcfg.bF.TSEG2 = 15; ciNbtcfg.bF.SJW = 15; break; // All 250K case CAN_250K_500K: case CAN_250K_833K: case CAN_250K_1M: case CAN_250K_1M5: case CAN_250K_2M: case CAN_250K_3M: case CAN_250K_4M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 126; ciNbtcfg.bF.TSEG2 = 31; ciNbtcfg.bF.SJW = 31; break; case CAN_1000K_4M: case CAN_1000K_8M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 30; ciNbtcfg.bF.TSEG2 = 7; ciNbtcfg.bF.SJW = 7; break; case CAN_125K_500K: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 254; ciNbtcfg.bF.TSEG2 = 63; ciNbtcfg.bF.SJW = 63; break; default: return -1; break; } // Write Bit time registers spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiNBTCFG, ciNbtcfg.word); return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigureData40MHz(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode) { int8_t spiTransferError = 0; REG_CiDBTCFG ciDbtcfg; REG_CiTDC ciTdc; // sspMode; ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4]; ciTdc.word = 0; // Configure Bit time and sample point ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO; uint32_t tdcValue = 0; // Data Bit rate and SSP switch (bitTime) { case CAN_500K_1M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 30; ciDbtcfg.bF.TSEG2 = 7; ciDbtcfg.bF.SJW = 7; // SSP ciTdc.bF.TDCOffset = 31; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_2M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 14; ciDbtcfg.bF.TSEG2 = 3; ciDbtcfg.bF.SJW = 3; // SSP ciTdc.bF.TDCOffset = 15; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_3M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 8; ciDbtcfg.bF.TSEG2 = 2; ciDbtcfg.bF.SJW = 2; // SSP ciTdc.bF.TDCOffset = 9; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_4M: case CAN_1000K_4M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 6; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 7; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_5M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 4; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 5; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_6M7: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 3; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 4; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_8M: case CAN_1000K_8M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 2; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 3; ciTdc.bF.TDCValue = 1; break; case CAN_500K_10M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 1; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 2; ciTdc.bF.TDCValue = 0; break; case CAN_250K_500K: case CAN_125K_500K: ciDbtcfg.bF.BRP = 1; ciDbtcfg.bF.TSEG1 = 30; ciDbtcfg.bF.TSEG2 = 7; ciDbtcfg.bF.SJW = 7; // SSP ciTdc.bF.TDCOffset = 31; ciTdc.bF.TDCValue = tdcValue; ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; break; case CAN_250K_833K: ciDbtcfg.bF.BRP = 1; ciDbtcfg.bF.TSEG1 = 17; ciDbtcfg.bF.TSEG2 = 4; ciDbtcfg.bF.SJW = 4; // SSP ciTdc.bF.TDCOffset = 18; ciTdc.bF.TDCValue = tdcValue; ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; break; case CAN_250K_1M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 30; ciDbtcfg.bF.TSEG2 = 7; ciDbtcfg.bF.SJW = 7; // SSP ciTdc.bF.TDCOffset = 31; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_1M5: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 18; ciDbtcfg.bF.TSEG2 = 5; ciDbtcfg.bF.SJW = 5; // SSP ciTdc.bF.TDCOffset = 19; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_2M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 14; ciDbtcfg.bF.TSEG2 = 3; ciDbtcfg.bF.SJW = 3; // SSP ciTdc.bF.TDCOffset = 15; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_3M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 8; ciDbtcfg.bF.TSEG2 = 2; ciDbtcfg.bF.SJW = 2; // SSP ciTdc.bF.TDCOffset = 9; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_4M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 6; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 7; ciTdc.bF.TDCValue = tdcValue; break; default: return -1; break; } // Write Bit time registers spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiDBTCFG, ciDbtcfg.word); if (spiTransferError) { return -2; } // Write Transmitter Delay Compensation #ifdef REV_A ciTdc.bF.TDCOffset = 0; ciTdc.bF.TDCValue = 0; #endif spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTDC, ciTdc.word); if (spiTransferError) { return -3; } return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigureNominal20MHz(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime) { int8_t spiTransferError = 0; REG_CiNBTCFG ciNbtcfg; ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4]; // Arbitration Bit rate switch (bitTime) { // All 500K case CAN_500K_1M: case CAN_500K_2M: case CAN_500K_4M: case CAN_500K_5M: case CAN_500K_6M7: case CAN_500K_8M: case CAN_500K_10M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 30; ciNbtcfg.bF.TSEG2 = 7; ciNbtcfg.bF.SJW = 7; break; // All 250K case CAN_250K_500K: case CAN_250K_833K: case CAN_250K_1M: case CAN_250K_1M5: case CAN_250K_2M: case CAN_250K_3M: case CAN_250K_4M: Serial.println("CAN BUS Shield init ok!"); ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 62; ciNbtcfg.bF.TSEG2 = 15; ciNbtcfg.bF.SJW = 15; break; case CAN_1000K_4M: case CAN_1000K_8M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 14; ciNbtcfg.bF.TSEG2 = 3; ciNbtcfg.bF.SJW = 3; break; case CAN_125K_500K: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 126; ciNbtcfg.bF.TSEG2 = 31; ciNbtcfg.bF.SJW = 31; break; default: return -1; break; } // Write Bit time registers spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiNBTCFG, ciNbtcfg.word); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigureData20MHz(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode) { int8_t spiTransferError = 0; REG_CiDBTCFG ciDbtcfg; REG_CiTDC ciTdc; // sspMode; ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4]; ciTdc.word = 0; // Configure Bit time and sample point ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO; uint32_t tdcValue = 0; // Data Bit rate and SSP switch (bitTime) { case CAN_500K_1M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 14; ciDbtcfg.bF.TSEG2 = 3; ciDbtcfg.bF.SJW = 3; // SSP ciTdc.bF.TDCOffset = 15; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_2M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 6; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 7; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_4M: case CAN_1000K_4M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 2; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 3; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_5M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 1; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 2; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_6M7: case CAN_500K_8M: case CAN_500K_10M: case CAN_1000K_8M: //qDebug("Data Bitrate not feasible with this clock!"); return -1; break; case CAN_250K_500K: case CAN_125K_500K: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 30; ciDbtcfg.bF.TSEG2 = 7; ciDbtcfg.bF.SJW = 7; // SSP ciTdc.bF.TDCOffset = 31; ciTdc.bF.TDCValue = tdcValue; ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; break; case CAN_250K_833K: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 17; ciDbtcfg.bF.TSEG2 = 4; ciDbtcfg.bF.SJW = 4; // SSP ciTdc.bF.TDCOffset = 18; ciTdc.bF.TDCValue = tdcValue; ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; break; case CAN_250K_1M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 14; ciDbtcfg.bF.TSEG2 = 3; ciDbtcfg.bF.SJW = 3; // SSP ciTdc.bF.TDCOffset = 15; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_1M5: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 8; ciDbtcfg.bF.TSEG2 = 2; ciDbtcfg.bF.SJW = 2; // SSP ciTdc.bF.TDCOffset = 9; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_2M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 6; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 7; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_3M: //qDebug("Data Bitrate not feasible with this clock!"); return -1; break; case CAN_250K_4M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 2; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 3; ciTdc.bF.TDCValue = tdcValue; break; default: return -1; break; } // Write Bit time registers spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiDBTCFG, ciDbtcfg.word); if (spiTransferError) { return -2; } // Write Transmitter Delay Compensation #ifdef REV_A ciTdc.bF.TDCOffset = 0; ciTdc.bF.TDCValue = 0; #endif spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTDC, ciTdc.word); if (spiTransferError) { return -3; } return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigureNominal10MHz(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime) { int8_t spiTransferError = 0; REG_CiNBTCFG ciNbtcfg; ciNbtcfg.word = canControlResetValues[cREGADDR_CiNBTCFG / 4]; // Arbitration Bit rate switch (bitTime) { // All 500K case CAN_500K_1M: case CAN_500K_2M: case CAN_500K_4M: case CAN_500K_5M: case CAN_500K_6M7: case CAN_500K_8M: case CAN_500K_10M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 14; ciNbtcfg.bF.TSEG2 = 3; ciNbtcfg.bF.SJW = 3; break; // All 250K case CAN_250K_500K: case CAN_250K_833K: case CAN_250K_1M: case CAN_250K_1M5: case CAN_250K_2M: case CAN_250K_3M: case CAN_250K_4M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 30; ciNbtcfg.bF.TSEG2 = 7; ciNbtcfg.bF.SJW = 7; break; case CAN_1000K_4M: case CAN_1000K_8M: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 7; ciNbtcfg.bF.TSEG2 = 2; ciNbtcfg.bF.SJW = 2; break; case CAN_125K_500K: ciNbtcfg.bF.BRP = 0; ciNbtcfg.bF.TSEG1 = 62; ciNbtcfg.bF.TSEG2 = 15; ciNbtcfg.bF.SJW = 15; break; default: return -1; break; } // Write Bit time registers spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiNBTCFG, ciNbtcfg.word); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_BitTimeConfigureData10MHz(CANFDSPI_MODULE_ID index, CAN_BITTIME_SETUP bitTime, CAN_SSP_MODE sspMode) { int8_t spiTransferError = 0; REG_CiDBTCFG ciDbtcfg; REG_CiTDC ciTdc; // sspMode; ciDbtcfg.word = canControlResetValues[cREGADDR_CiDBTCFG / 4]; ciTdc.word = 0; // Configure Bit time and sample point ciTdc.bF.TDCMode = CAN_SSP_MODE_AUTO; uint32_t tdcValue = 0; // Data Bit rate and SSP switch (bitTime) { case CAN_500K_1M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 6; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 7; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_2M: // Data BR ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 2; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 3; ciTdc.bF.TDCValue = tdcValue; break; case CAN_500K_4M: case CAN_500K_5M: case CAN_500K_6M7: case CAN_500K_8M: case CAN_500K_10M: case CAN_1000K_4M: case CAN_1000K_8M: //qDebug("Data Bitrate not feasible with this clock!"); return -1; break; case CAN_250K_500K: case CAN_125K_500K: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 14; ciDbtcfg.bF.TSEG2 = 3; ciDbtcfg.bF.SJW = 3; // SSP ciTdc.bF.TDCOffset = 15; ciTdc.bF.TDCValue = tdcValue; ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; break; case CAN_250K_833K: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 7; ciDbtcfg.bF.TSEG2 = 2; ciDbtcfg.bF.SJW = 2; // SSP ciTdc.bF.TDCOffset = 8; ciTdc.bF.TDCValue = tdcValue; ciTdc.bF.TDCMode = CAN_SSP_MODE_OFF; break; case CAN_250K_1M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 6; ciDbtcfg.bF.TSEG2 = 1; ciDbtcfg.bF.SJW = 1; // SSP ciTdc.bF.TDCOffset = 7; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_1M5: //qDebug("Data Bitrate not feasible with this clock!"); return -1; break; case CAN_250K_2M: ciDbtcfg.bF.BRP = 0; ciDbtcfg.bF.TSEG1 = 2; ciDbtcfg.bF.TSEG2 = 0; ciDbtcfg.bF.SJW = 0; // SSP ciTdc.bF.TDCOffset = 3; ciTdc.bF.TDCValue = tdcValue; break; case CAN_250K_3M: case CAN_250K_4M: //qDebug("Data Bitrate not feasible with this clock!"); return -1; break; default: return -1; break; } // Write Bit time registers spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiDBTCFG, ciDbtcfg.word); if (spiTransferError) { return -2; } // Write Transmitter Delay Compensation #ifdef REV_A ciTdc.bF.TDCOffset = 0; ciTdc.bF.TDCValue = 0; #endif spiTransferError = DRV_CANFDSPI_WriteWord(index, cREGADDR_CiTDC, ciTdc.word); if (spiTransferError) { return -3; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: GPIO int8_t DRV_CANFDSPI_GpioModeConfigure(CANFDSPI_MODULE_ID index, GPIO_PIN_MODE gpio0, GPIO_PIN_MODE gpio1) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON + 3; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); if (spiTransferError) { return -1; } // Modify iocon.bF.PinMode0 = gpio0; iocon.bF.PinMode1 = gpio1; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioDirectionConfigure(CANFDSPI_MODULE_ID index, GPIO_PIN_DIRECTION gpio0, GPIO_PIN_DIRECTION gpio1) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[0]); if (spiTransferError) { return -1; } // Modify iocon.bF.TRIS0 = gpio0; iocon.bF.TRIS1 = gpio1; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioStandbyControlEnable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[0]); if (spiTransferError) { return -1; } // Modify iocon.bF.XcrSTBYEnable = 1; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioStandbyControlDisable(CANFDSPI_MODULE_ID index) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[0]); if (spiTransferError) { return -1; } // Modify iocon.bF.XcrSTBYEnable = 0; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[0]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioInterruptPinsOpenDrainConfigure(CANFDSPI_MODULE_ID index, GPIO_OPEN_DRAIN_MODE mode) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON + 3; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); if (spiTransferError) { return -1; } // Modify iocon.bF.INTPinOpenDrain = mode; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioTransmitPinOpenDrainConfigure(CANFDSPI_MODULE_ID index, GPIO_OPEN_DRAIN_MODE mode) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON + 3; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); if (spiTransferError) { return -1; } // Modify iocon.bF.TXCANOpenDrain = mode; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioPinSet(CANFDSPI_MODULE_ID index, GPIO_PIN_POS pos, GPIO_PIN_STATE latch) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON + 1; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[1]); if (spiTransferError) { return -1; } // Modify switch (pos) { case GPIO_PIN_0: iocon.bF.LAT0 = latch; break; case GPIO_PIN_1: iocon.bF.LAT1 = latch; break; default: return -1; break; } // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[1]); if (spiTransferError) { return -2; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioPinRead(CANFDSPI_MODULE_ID index, GPIO_PIN_POS pos, GPIO_PIN_STATE* state) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON + 2; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[2]); if (spiTransferError) { return -1; } // Update data switch (pos) { case GPIO_PIN_0: *state = (GPIO_PIN_STATE) iocon.bF.GPIO0; break; case GPIO_PIN_1: *state = (GPIO_PIN_STATE) iocon.bF.GPIO1; break; default: return -1; break; } return spiTransferError; } int8_t DRV_CANFDSPI_GpioClockOutputConfigure(CANFDSPI_MODULE_ID index, GPIO_CLKO_MODE mode) { int8_t spiTransferError = 0; uint16_t a = 0; // Read a = cREGADDR_IOCON + 3; REG_IOCON iocon; iocon.word = 0; spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &iocon.byte[3]); if (spiTransferError) { return -1; } // Modify iocon.bF.SOFOutputEnable = mode; // Write spiTransferError = DRV_CANFDSPI_WriteByte(index, a, iocon.byte[3]); if (spiTransferError) { return -2; } return spiTransferError; } // ***************************************************************************** // ***************************************************************************** // Section: Miscellaneous uint32_t DRV_CANFDSPI_DlcToDataBytes(CAN_DLC dlc) { uint32_t dataBytesInObject = 0; Nop(); Nop(); if (dlc < CAN_DLC_12) { dataBytesInObject = dlc; } else { switch (dlc) { case CAN_DLC_12: dataBytesInObject = 12; break; case CAN_DLC_16: dataBytesInObject = 16; break; case CAN_DLC_20: dataBytesInObject = 20; break; case CAN_DLC_24: dataBytesInObject = 24; break; case CAN_DLC_32: dataBytesInObject = 32; break; case CAN_DLC_48: dataBytesInObject = 48; break; case CAN_DLC_64: dataBytesInObject = 64; break; default: break; } } return dataBytesInObject; } int8_t DRV_CANFDSPI_FifoIndexGet(CANFDSPI_MODULE_ID index, CAN_FIFO_CHANNEL channel, uint8_t* mi) { int8_t spiTransferError = 0; uint16_t a = 0; // Read Status register uint8_t b = 0; a = cREGADDR_CiFIFOSTA + (channel * CiFIFO_OFFSET); a += 1; // byte[1] spiTransferError = DRV_CANFDSPI_ReadByte(index, a, &b); if (spiTransferError) { return -1; } // Update data *mi = b & 0x1f; return spiTransferError; } uint16_t DRV_CANFDSPI_CalculateCRC16(uint8_t* data, uint16_t size) { uint16_t init = CRCBASE; uint8_t index; while (size-- != 0) { index = ((uint8_t*) & init)[CRCUPPER] ^ *data++; init = (init << 8) ^ crc16_table[index]; } return init; } CAN_DLC DRV_CANFDSPI_DataBytesToDlc(uint8_t n) { CAN_DLC dlc = CAN_DLC_0; if (n <= 4) { dlc = CAN_DLC_4; } else if (n <= 8) { dlc = CAN_DLC_8; } else if (n <= 12) { dlc = CAN_DLC_12; } else if (n <= 16) { dlc = CAN_DLC_16; } else if (n <= 20) { dlc = CAN_DLC_20; } else if (n <= 24) { dlc = CAN_DLC_24; } else if (n <= 32) { dlc = CAN_DLC_32; } else if (n <= 48) { dlc = CAN_DLC_48; } else if (n <= 64) { dlc = CAN_DLC_64; } return dlc; }