Mercurial > public > ostc4
view Small_CPU/Src/spi.c @ 224:ceecabfddb57 div-fixes-3
Bugfix, deco: fix 2 (small) problems with calculated ceiling
This fixes 1 trivial, and 1 not really trivial bug in the calculation
of the ceiling. When simulating a bounce dive to 80m, things become
clear (tried this on a CCR dive, fixed setpoint 1.2bar, about 15 minutes
of bottom time). Closely watch the behavior of the ceiling data. At some
point during the ascent, the ceiling begins to decrease in 10cm steps.
Then suddenly (while still ascending), the ceiling increases again with 1m,
does not change for some time, and then suddenly steps 1.1m less deep.
While not very relevant to real deco diving, it is simply wrong.
The reason for this is subtle. The algorithm used to find the ceiling
is a sort of linear search, stepping down a meter, overshoot the depth, and
search back in 10cm steps. It seems some numerical instability. Fixing
this, was a bit more computational intensive search by stepping up down in
equal steps of 10cm. But, I'm pretty sure that things can be speeded up here, as a
ceiling does not change fast, so it should be not that difficult to limit
the search space, or use a binary search algorithm instead.
The trivial second problem fixed, is that the ceiling ends at the surface
and not at 1m depth. This small issue became visible after changing the step
down size above.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Sun, 31 Mar 2019 19:35:51 +0200 |
parents | 9fc06e1e0f66 |
children | e4207f0aaa4b |
line wrap: on
line source
/** ****************************************************************************** * @file spi.c * @author heinrichs weikamp gmbh * @version V0.0.1 * @date 16-Sept-2014 * @brief Source code for spi control * @verbatim ============================================================================== ##### How to use ##### ============================================================================== @endverbatim ****************************************************************************** * @attention * * <h2><center>© COPYRIGHT(c) 2014 heinrichs weikamp</center></h2> * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "global_constants.h" #include "spi.h" #include "dma.h" //#include "gpio.h" /* USER CODE BEGIN 0 */ #include "scheduler.h" #ifdef DEBUG_GPIO extern void GPIO_new_DEBUG_LOW(void); extern void GPIO_new_DEBUG_HIGH(void); #endif uint8_t data_error = 0; uint32_t data_error_time = 0; uint8_t SPIDataRX = 0; /* Flag to signal that SPI RX callback has been triggered */ static void SPI_Error_Handler(void); /* USER CODE END 0 */ static uint8_t SPI_check_header_and_footer_ok(void); static uint8_t DataEX_check_header_and_footer_shifted(void); SPI_HandleTypeDef hspi1; SPI_HandleTypeDef hspi3; DMA_HandleTypeDef hdma_tx; DMA_HandleTypeDef hdma_rx; // SPI3 init function void MX_SPI3_Init(void) { hspi3.Instance = SPI3; hspi3.Init.Mode = SPI_MODE_MASTER; hspi3.Init.Direction = SPI_DIRECTION_2LINES; hspi3.Init.DataSize = SPI_DATASIZE_8BIT; hspi3.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi3.Init.CLKPhase = SPI_PHASE_1EDGE; hspi3.Init.NSS = SPI_NSS_SOFT; hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi3.Init.TIMode = SPI_TIMODE_DISABLED; hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; hspi3.Init.CRCPolynomial = 7; HAL_SPI_Init(&hspi3); } void MX_SPI3_DeInit(void) { HAL_SPI_DeInit(&hspi3); } uint8_t SPI3_ButtonAdjust(uint8_t *arrayInput, uint8_t *arrayOutput) { HAL_StatusTypeDef status; uint8_t answer[10]; uint8_t rework[10]; rework[0] = 0xFF; for (int i = 0; i < 3; i++) { // limiter if (arrayInput[i] == 0xFF) arrayInput[i] = 0xFE; if (arrayInput[i] >= 15) { // copy - ausl�se-schwelle rework[i + 1] = arrayInput[i]; // wieder-scharf-schalte-schwelle rework[i + 3 + 1] = arrayInput[i] - 10; } else if (arrayInput[i] >= 10) { // copy - ausl�se-schwelle rework[i + 1] = arrayInput[i]; // wieder-scharf-schalte-schwelle rework[i + 3 + 1] = arrayInput[i] - 5; } else { // copy - ausl�se-schwelle rework[i + 1] = 7; // wieder-scharf-schalte-schwelle rework[i + 3 + 1] = 6; } } status = HAL_OK; /* = 0 */ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET); for (int i = 0; i < 7; i++) { HAL_Delay(10); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_RESET); HAL_Delay(10); status += HAL_SPI_TransmitReceive(&hspi3, &rework[i], &answer[i], 1, 20); HAL_Delay(10); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET); } if (status == HAL_OK) { for (int i = 0; i < 3; i++) { arrayOutput[i] = answer[i + 2]; // first not, return of 0xFF not } return 1; } else return 0; } // SPI5 init function void MX_SPI1_Init(void) { hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_SLAVE; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_LOW; hspi1.Init.CLKPhase = SPI_PHASE_1EDGE; hspi1.Init.NSS = SPI_NSS_HARD_INPUT; //SPI_NSS_SOFT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLED; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED; //_DISABLED; _ENABLED; hspi1.Init.CRCPolynomial = 7; HAL_SPI_Init(&hspi1); } void MX_SPI_DeInit(void) { HAL_SPI_DeInit(&hspi1); } void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) { GPIO_InitTypeDef GPIO_InitStruct; if (hspi->Instance == SPI1) { SPIDataRX = 0; // Peripheral clock enable __SPI1_CLK_ENABLE(); __GPIOA_CLK_ENABLE(); //SPI1 GPIO Configuration //PA4 ------> SPI1_CS //PA5 ------> SPI1_SCK //PA6 ------> SPI1_MISO //PA7 ------> SPI1_MOSI GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; // GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; /* Decision is based on errata which recommends FAST for GPIO at 90Mhz */ GPIO_InitStruct.Alternate = GPIO_AF5_SPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); //##-3- Configure the DMA streams ########################################## // Configure the DMA handler for Transmission process hdma_tx.Instance = DMA2_Stream3; hdma_tx.Init.Channel = DMA_CHANNEL_3; hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_tx.Init.MemInc = DMA_MINC_ENABLE; hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_tx.Init.Mode = DMA_NORMAL; hdma_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH; hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_tx.Init.MemBurst = DMA_MBURST_INC4; hdma_tx.Init.PeriphBurst = DMA_PBURST_INC4; HAL_DMA_Init(&hdma_tx); // Associate the initialized DMA handle to the the SPI handle __HAL_LINKDMA(hspi, hdmatx, hdma_tx); // Configure the DMA handler for Transmission process hdma_rx.Instance = DMA2_Stream0; hdma_rx.Init.Channel = DMA_CHANNEL_3; hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_rx.Init.MemInc = DMA_MINC_ENABLE; hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; hdma_rx.Init.Mode = DMA_NORMAL; hdma_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE; hdma_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; hdma_rx.Init.MemBurst = DMA_MBURST_INC4; hdma_rx.Init.PeriphBurst = DMA_PBURST_INC4; HAL_DMA_Init(&hdma_rx); // Associate the initialized DMA handle to the the SPI handle __HAL_LINKDMA(hspi, hdmarx, hdma_rx); //##-4- Configure the NVIC for DMA ######################################### //NVIC configuration for DMA transfer complete interrupt (SPI3_RX) HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 1, 0); HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn); // NVIC configuration for DMA transfer complete interrupt (SPI1_TX) HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 1, 1); HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); } else if (hspi->Instance == SPI3) { __GPIOC_CLK_ENABLE(); __SPI3_CLK_ENABLE(); //SPI1 GPIO Configuration //PC10 ------> SPI3_SCK //PC11 ------> SPI3_MISO //PC12 ------> SPI3_MOSI //PA15 ------> SPI3_NSS (official) //PC9 ------> SPI3_NSS (hw) GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; GPIO_InitStruct.Alternate = GPIO_AF6_SPI3; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_9, GPIO_PIN_SET); } } void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) { if (hspi->Instance == SPI1) { __SPI1_FORCE_RESET(); __SPI1_RELEASE_RESET(); //SPI1 GPIO Configuration //PA5 ------> SPI1_SCK //PA6 ------> SPI1_MISO //PA7 ------> SPI1_MOSI HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7); HAL_DMA_DeInit(&hdma_tx); HAL_DMA_DeInit(&hdma_rx); HAL_NVIC_DisableIRQ(DMA2_Stream3_IRQn); HAL_NVIC_DisableIRQ(DMA2_Stream0_IRQn); } else if (hspi->Instance == SPI3) { __SPI3_FORCE_RESET(); __SPI3_RELEASE_RESET(); //SPI1 GPIO Configuration //PC10 ------> SPI3_SCK //PC11 ------> SPI3_MISO //PC12 ------> SPI3_MOSI //PA15 ------> SPI3_NSS (official) //PC9 ------> SPI3_NSS (hw) HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12); } } void SPI_synchronize_with_Master(void) { #ifdef USE_OLD_SYNC_METHOD GPIO_InitTypeDef GPIO_InitStruct; // __GPIOA_CLK_ENABLE(); /**SPI1 GPIO Configuration PA5 ------> SPI1_SCK */ GPIO_InitStruct.Pin = GPIO_PIN_4 | GPIO_PIN_5; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FAST; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // HAL_Delay(10); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4) == 0); HAL_Delay(10); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5) == 1); HAL_Delay(50); #endif } void SPI_Start_single_TxRx_with_Master(void) { uint8_t * pOutput; HAL_StatusTypeDef retval; if (global.dataSendToSlave.getDeviceDataNow) { global.dataSendToSlave.getDeviceDataNow = 0; pOutput = (uint8_t*) &(global.deviceDataSendToMaster); } else { pOutput = (uint8_t*) &(global.dataSendToMaster); } retval = HAL_SPI_TransmitReceive_DMA(&hspi1, pOutput,(uint8_t*) &(global.dataSendToSlave), EXCHANGE_BUFFERSIZE); if ( retval!= HAL_OK) { SPI_Error_Handler(); } } void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi) { /* restart SPI */ if (hspi == &hspi1) { Scheduler_SyncToSPI(); SPIDataRX = 1; /* stop data exchange? */ if (global.mode == MODE_SHUTDOWN) { global.mode = MODE_SLEEP; global.dataSendToSlavePending = 0; global.dataSendToSlaveIsValid = 1; global.dataSendToSlaveIsNotValidCount = 0; } } } void SPI_Evaluate_RX_Data() { uint8_t resettimeout = 1; if ((global.mode != MODE_SHUTDOWN) && ( global.mode != MODE_SLEEP) && (SPIDataRX)) { SPIDataRX = 0; /* data consistent? */ if (SPI_check_header_and_footer_ok()) { global.dataSendToMaster.header.checkCode[SPI_HEADER_INDEX_RX_STATE] = SPI_RX_STATE_OK; // GPIO_new_DEBUG_HIGH(); //For debug. global.dataSendToSlaveIsValid = 1; global.dataSendToSlaveIsNotValidCount = 0; /* Master signal a data shift outside of his control => reset own DMA and resync */ if(global.dataSendToSlave.header.checkCode[SPI_HEADER_INDEX_RX_STATE] == SPI_RX_STATE_SHIFTED) { HAL_SPI_Abort_IT(&hspi1); Scheduler_Request_sync_with_SPI(SPI_SYNC_METHOD_HARD); } else { } } else { // GPIO_new_DEBUG_LOW(); //For debug. global.dataSendToSlaveIsValid = 0; global.dataSendToSlaveIsNotValidCount++; if(DataEX_check_header_and_footer_shifted()) { /* Reset own DMA */ if ((global.dataSendToSlaveIsNotValidCount % 10) == 1) //% 10 { HAL_SPI_Abort_IT(&hspi1); /* reset DMA only once */ } /* Signal problem to master */ if ((global.dataSendToSlaveIsNotValidCount ) >= 2) { global.dataSendToMaster.header.checkCode[SPI_HEADER_INDEX_RX_STATE] = SPI_RX_STATE_SHIFTED; } } else /* handle received data as if no data would have been received */ { global.dataSendToMaster.header.checkCode[SPI_HEADER_INDEX_RX_STATE] = SPI_RX_STATE_OFFLINE; resettimeout = 0; } } global.dataSendToMaster.power_on_reset = 0; global.deviceDataSendToMaster.power_on_reset = 0; //TODO:REMOVE // if ( !global.dataSendToSlaveStopEval ) { // scheduleSpecial_Evaluate_DataSendToSlave(); // } scheduleSpecial_Evaluate_DataSendToSlave(); SPI_Start_single_TxRx_with_Master(); } if(resettimeout) { global.check_sync_not_running = 0; } } static uint8_t SPI_check_header_and_footer_ok(void) { if (global.dataSendToSlave.header.checkCode[0] != 0xBB) return 0; #ifdef USE_OLD_HEADER_FORMAT if (global.dataSendToSlave.header.checkCode[1] != 0x01) return 0; if (global.dataSendToSlave.header.checkCode[2] != 0x01) return 0; #endif if (global.dataSendToSlave.header.checkCode[3] != 0xBB) return 0; if (global.dataSendToSlave.footer.checkCode[0] != 0xF4) return 0; if (global.dataSendToSlave.footer.checkCode[1] != 0xF3) return 0; if (global.dataSendToSlave.footer.checkCode[2] != 0xF2) return 0; if (global.dataSendToSlave.footer.checkCode[3] != 0xF1) return 0; return 1; } /* Check if there is an empty frame providec by RTE (all 0) or even no data provided by RTE (all 0xFF) * If that is not the case the DMA is somehow not in sync */ uint8_t DataEX_check_header_and_footer_shifted() { uint8_t ret = 1; if((global.dataSendToSlave.footer.checkCode[0] == 0x00) && (global.dataSendToSlave.footer.checkCode[1] == 0x00) && (global.dataSendToSlave.footer.checkCode[2] == 0x00) && (global.dataSendToSlave.footer.checkCode[3] == 0x00)) { ret = 0; } if((global.dataSendToSlave.footer.checkCode[0] == 0xff) && (global.dataSendToSlave.footer.checkCode[1] == 0xff) && (global.dataSendToSlave.footer.checkCode[2] == 0xff) && (global.dataSendToSlave.footer.checkCode[3] == 0xff)) { ret = 0; } return ret; } static void SPI_Error_Handler(void) { //The device is locks. Hard to recover. // while(1) // { // } } /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/