Push local changes for complete and functioning probe

main
Adam Prochazka 2 years ago
parent 836ab547df
commit ea70f82c92

File diff suppressed because one or more lines are too long

@ -1,3 +1,12 @@
/**
******************************************************************************
* @file : Cam.c
* @brief : Interacting with camera module
* This file contains the methods for communication with camera module, including I2C and SPI communication, sending commands to camera and reading data from it.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
*/
#include "Cam.h"
void CS_Off()
@ -120,19 +129,24 @@ void Cam_I2C_write_bulk(I2C_HandleTypeDef *hi2c, const struct sensor_reg regList
void Cam_Init(I2C_HandleTypeDef *hi2c, SPI_HandleTypeDef *hspi)
{
// Test SPI communication
Cam_SPI_write(hspi, 0x07, 0x80);
HAL_Delay(100);
Cam_SPI_write(hspi, 0x07, 0x00);
HAL_Delay(100);
// Reset camera chip
Cam_I2C_write(hi2c, (uint16_t)0x3008, 0x80);
// Delay for reset complete.
HAL_Delay(5);
// Set registers for desired configuration - need to be in this specific order
Cam_I2C_write_bulk(hi2c, OV5642_QVGA_Preview);
HAL_Delay(200);
HAL_Delay(200); // Delay for first configuration to take effect
Cam_I2C_write_bulk(hi2c, OV5642_JPEG_Capture_QSXGA);
Cam_I2C_write_bulk(hi2c, ov5642_1024x768);
//Cam_I2C_write_bulk(hi2c, ov5642_320x240);
HAL_Delay(100);
Cam_I2C_write(hi2c, (uint16_t)0x3818, 0xa8); // TIMING CONTROL - ENABLE COMPRESSION, THUMBNAIL MODE DISABLE, VERTICAL FLIP, MIRROR
@ -141,16 +155,17 @@ void Cam_Init(I2C_HandleTypeDef *hi2c, SPI_HandleTypeDef *hspi)
Cam_I2C_write(hi2c, (uint16_t)0x4407, 0x09); // COMPRESSION CONTROL
HAL_Delay(5);
// Setup camera, H-sync: High, V-sync:high, Sensor_delay: no Delay, FIFO_mode:FIFO enabled, power_mode:Low_power
// H-sync: High, V-sync:high, Sensor_delay: no Delay, FIFO_mode:FIFO enabled, power_mode:Low_power
Cam_SPI_write(hspi, 0x03, 0x02);
HAL_Delay(5);
Cam_I2C_write_bulk(hi2c, ov5642_1024x768);
//Cam_I2C_write_bulk(hi2c, ov5642_320x240);
HAL_Delay(1000);
Cam_I2C_write_bulk(hi2c, ov5642_1024x768); // Necessary to be called again
HAL_Delay(1000); // Delay for camera to stabilize
Cam_SPI_write(hspi, 0x04, 0x01);
Cam_SPI_write(hspi, 0x04, 0x01); // Reset camera capture status and memory flags
HAL_Delay(5);
@ -159,145 +174,32 @@ void Cam_Init(I2C_HandleTypeDef *hi2c, SPI_HandleTypeDef *hspi)
HAL_Delay(5);
}
void Cam_Refresh(I2C_HandleTypeDef *hi2c, SPI_HandleTypeDef *hspi){
/*Cam_I2C_write(hi2c, (uint16_t)0x3008, 0x80);
Cam_I2C_write_bulk(hi2c, OV5642_QVGA_Preview);
Cam_I2C_write_bulk(hi2c, OV5642_JPEG_Capture_QSXGA);
Cam_I2C_write(hi2c, (uint16_t)0x3818, 0xa8); // TIMING CONTROL - ENABLE COMPRESSION, THUMBNAIL MODE DISABLE, VERTICAL FLIP, MIRROR
Cam_I2C_write(hi2c, (uint16_t)0x3621, 0x10); // REGISTER FOR CORRECT MIRROR FUNCTION
Cam_I2C_write(hi2c, (uint16_t)0x3801, 0xb0); // TIMING HORIZONTAL START - ALSO FOR MIRROR
Cam_I2C_write(hi2c, (uint16_t)0x4407, 0x04); // COMPRESSION CONTROL
Cam_I2C_write_bulk(hi2c, ov5642_1280x960);
// Setup camera, H-sync: High, V-sync:high, Sensor_delay: no Delay, FIFO_mode:FIFO enabled, power_mode:Low_power
Cam_SPI_write(hspi, 0x03, 0x02);
Cam_SPI_write(hspi, 0x01, 0x00); // Capture Control Register - Set to capture n+1 frames
HAL_Delay(5);*/
// SAFE TO REMOVE
//Cam_I2C_write(hi2c, (uint16_t)0x3008, 0x80);
Cam_I2C_write_bulk(hi2c, OV5642_QVGA_Preview);
Cam_I2C_write_bulk(hi2c, OV5642_JPEG_Capture_QSXGA);
Cam_I2C_write(hi2c, (uint16_t)0x3818, 0xa8); // TIMING CONTROL - ENABLE COMPRESSION, THUMBNAIL MODE DISABLE, VERTICAL FLIP, MIRROR
Cam_I2C_write(hi2c, (uint16_t)0x3621, 0x10); // REGISTER FOR CORRECT MIRROR FUNCTION
Cam_I2C_write(hi2c, (uint16_t)0x3801, 0xb0); // TIMING HORIZONTAL START - ALSO FOR MIRROR
Cam_I2C_write(hi2c, (uint16_t)0x4407, 0x04); // COMPRESSION CONTROL
Cam_I2C_write(hi2c, (uint16_t)0x5000, 0xFF);
Cam_I2C_write_bulk(hi2c, ov5642_1024x768);
// Setup camera, H-sync: High, V-sync:high, Sensor_delay: no Delay, FIFO_mode:FIFO enabled, power_mode:Low_power
Cam_SPI_write(hspi, 0x03, 0x02);
// Brightness 4
Cam_I2C_write(hi2c, (uint16_t)0x5001, 0xff);
Cam_I2C_write(hi2c, (uint16_t)0x5589, 0x30);
Cam_I2C_write(hi2c, (uint16_t)0x5580, 0x04);
Cam_I2C_write(hi2c, (uint16_t)0x558a, 0x00);
//Cam_I2C_write(hi2c, (uint16_t)0x558a, 0x08);
//Contrast 0
//Cam_I2C_write(hi2c, (uint16_t)0x5587, 0xff);
//Cam_I2C_write(hi2c, (uint16_t)0x5588, 0xff);
/*
// Exposure _17
Cam_I2C_write(hi2c, (uint16_t)0x3a0f, 0x10);
Cam_I2C_write(hi2c, (uint16_t)0x3a10, 0x08);
Cam_I2C_write(hi2c, (uint16_t)0x3a1b, 0x10);
Cam_I2C_write(hi2c, (uint16_t)0x3a1e, 0x08);
Cam_I2C_write(hi2c, (uint16_t)0x3a11, 0x20);
Cam_I2C_write(hi2c, (uint16_t)0x3a1f, 0x10);
//Exposure 17 v2
Cam_I2C_write(hi2c, (uint16_t)0x3a0f, 0x60);
Cam_I2C_write(hi2c, (uint16_t)0x3a10, 0x58);
Cam_I2C_write(hi2c, (uint16_t)0x3a11, 0xa0);
Cam_I2C_write(hi2c, (uint16_t)0x3a1b, 0x60);
Cam_I2C_write(hi2c, (uint16_t)0x3a1e, 0x58);
Cam_I2C_write(hi2c, (uint16_t)0x3a1f, 0x20);
*/
// Exposure Manual
Cam_I2C_write(hi2c, (uint16_t)0x3503, 0x3);
Cam_I2C_write(hi2c, (uint16_t)0x350C, 0xFF);
Cam_I2C_write(hi2c, (uint16_t)0x350D, 0xFF);
Cam_I2C_write(hi2c, (uint16_t)0x3500, 0x0);
Cam_I2C_write(hi2c, (uint16_t)0x3501, 0x00);
Cam_I2C_write(hi2c, (uint16_t)0x3502, 0x0f);
//Gain MAX
Cam_I2C_write(hi2c, (uint16_t)0x350A, 0x0);
Cam_I2C_write(hi2c, (uint16_t)0x350B, 0x35);
Cam_I2C_write(hi2c, (uint16_t)0x3508, 0x0);
Cam_I2C_write(hi2c, (uint16_t)0x3509, 0x35);
// AWB
Cam_I2C_write(hi2c, (uint16_t)0x3406, 0x1);
Cam_I2C_write(hi2c, (uint16_t)0x3400, 0xf);
Cam_I2C_write(hi2c, (uint16_t)0x3401, 0xff);
Cam_I2C_write(hi2c, (uint16_t)0x3402, 0xf);
Cam_I2C_write(hi2c, (uint16_t)0x3403, 0x7f);
Cam_I2C_write(hi2c, (uint16_t)0x3404, 0xf);
Cam_I2C_write(hi2c, (uint16_t)0x3405, 0xff);
HAL_Delay(50);
}
int Cam_FIFO_length(SPI_HandleTypeDef *hspi)
{
uint32_t len1, len2, len3, len = 0;
len1 = Cam_SPI_read(hspi, 0x42);
len2 = Cam_SPI_read(hspi, 0x43);
len3 = Cam_SPI_read(hspi, 0x44)& 0x7f;
len = ((len3 << 16) | (len2 << 8) | len1) & 0x07fffff;
len = ((len3 << 16) | (len2 << 8) | len1) & 0x07fffff; // logic & operation needed, because content of the registry 0x44 isn't all length data.
return len;
}
void Cam_Start_Capture(SPI_HandleTypeDef *hspi)
{
/*
uint8_t FIFO_Reg = Cam_SPI_read(hspi, 0x04);
uint8_t FIFO_Reg_Clear_Flags = FIFO_Reg | 0x01;
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags); // Clear FIFO Write Done Flaf
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags);
HAL_Delay(1);
FIFO_Reg = Cam_SPI_read(hspi, 0x04);
FIFO_Reg_Clear_Flags = FIFO_Reg | 0x10;
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags); // Reset FIFO Write Pointer
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags);
HAL_Delay(1);
FIFO_Reg = Cam_SPI_read(hspi, 0x04);
FIFO_Reg_Clear_Flags = FIFO_Reg | 0x20;
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags); // Reset FIFO Read Pointer
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags);
*/
Cam_SPI_write(hspi, 0x04, 0x01);
// Reset memory pointers and capture status flags
Cam_SPI_write(hspi, 0x04, 0x01);
HAL_Delay(3);
Cam_SPI_write(hspi, 0x04, 0x01);
// Start capture
HAL_Delay(3);
Cam_SPI_write(hspi, 0x04, 0x02); // Start capture
Cam_SPI_write(hspi, 0x04, 0x02);
HAL_Delay(3);
}
void Cam_Wait_Capture_Done(SPI_HandleTypeDef *hspi)
{
// Check if bit meaning capture is done in registry 0x41 is set
while (1)
{
uint8_t regValue = Cam_SPI_read(hspi, 0x41);
@ -309,34 +211,25 @@ void Cam_Wait_Capture_Done(SPI_HandleTypeDef *hspi)
void Cam_Start_Burst_Read(SPI_HandleTypeDef *hspi)
{
/*
uint8_t FIFO_Reg = Cam_SPI_read(hspi, 0x04);
uint8_t FIFO_Reg_Clear_Flags = FIFO_Reg | 0x20;
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags); // Reset FIFO Read Pointer
Cam_SPI_write(hspi, 0x04, FIFO_Reg_Clear_Flags);
*/
// Reset memory pointers and capture status flags
Cam_SPI_write(hspi, 0x04, 0x01);
Cam_SPI_write(hspi, 0x04, 0x01);
uint8_t BURST_FIFO_READ = 0x3c;
uint8_t empty = 0x00;
// Set camera CS chip to high for SPI communication
CS_On();
// Send command for burst read
HAL_SPI_TransmitReceive(hspi, &BURST_FIFO_READ, &empty, 1, HAL_MAX_DELAY);
}
void Cam_Capture(SPI_HandleTypeDef *hspi)
{
//LED_On();
Cam_SPI_write(hspi, 0x01, 0x00); // Capture Control Register - Set to capture n+1 frames
Cam_Start_Capture(hspi);
Cam_Wait_Capture_Done(hspi);
//LED_Off();
}
}

@ -1,28 +1,128 @@
/**
******************************************************************************
* @file : Cam.h
* @brief : Methods for interacting with camera module
* This file contains the definitions the methods for interacting with camera module.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
*/
#include "OV5642_regs.h"
#include "stm32l4xx_hal.h"
/**
* @brief Disables the chip select line for the camera module.
*/
void CS_Off();
/**
* @brief Enables the chip select line for the camera module.
*/
void CS_On();
/**
* @brief Turns on the LED on Nucleo board.
*/
void LED_On();
/**
* @brief Turns on the LED on Nucleo board.
*/
void LED_Off();
/**
* @brief Turns on the optional debug LED.
*/
void Debug_LED_On();
/**
* @brief Turns off the optional debug LED.
*/
void Debug_LED_Off();
/**
* @brief Initializes SPI communication with the camera module.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
*/
void SPI_Init(SPI_HandleTypeDef *hspi);
/**
* @brief Reads data from the camera module using SPI.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
* @param address The address to read data from.
* @return The data read from the specified address.
*/
int Cam_SPI_read(SPI_HandleTypeDef *hspi, uint8_t address);
/**
* @brief Writes data to the camera module using SPI.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
* @param addr The address to write data to.
* @param data The data to write to the specified address.
* @return Status of the write operation (0 for success, non-zero for failure).
*/
int Cam_SPI_write(SPI_HandleTypeDef *hspi, uint8_t addr, uint8_t data);
/**
* @brief Writes data to the camera module using I2C.
* @param hi2c Pointer to an I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
* @param address The address to write data to.
* @param data The data to write to the specified address.
* @return Status of the write operation (1 for success, 0 for failure).
*/
int Cam_I2C_write(I2C_HandleTypeDef *hi2c, uint16_t address, uint8_t data);
/**
* @brief Writes a sensor register structure to the camera module using I2C.
* @param hi2c Pointer to an I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
* @param reg The sensor register structure to write.
* @return Status of the write operation (1 for success, 0 for failure).
*/
int Cam_I2C_write_struct(I2C_HandleTypeDef *hi2c, sensor_reg reg);
/**
* @brief Writes a list of sensor registers to the camera module using I2C.
* @param hi2c Pointer to an I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
* @param regList An array of sensor register structures to write.
*/
void Cam_I2C_write_bulk(I2C_HandleTypeDef *hi2c, const struct sensor_reg regList[]);
/**
* @brief Initializes the camera module.
* @param hi2c Pointer to an I2C_HandleTypeDef structure that contains the configuration information for the specified I2C.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
*/
void Cam_Init(I2C_HandleTypeDef *hi2c, SPI_HandleTypeDef *hspi);
void Cam_Refresh(I2C_HandleTypeDef *hi2c, SPI_HandleTypeDef *hspi);
/**
* @brief Retrieves the length of the FIFO buffer in the camera module.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
* @return The length of the FIFO buffer.
*/
int Cam_FIFO_length(SPI_HandleTypeDef *hspi);
/**
* @brief Captures an image using the camera module.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
*/
void Cam_Capture(SPI_HandleTypeDef *hspi);
/**
* @brief Starts the capture process in the camera module.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI
*/
void Cam_Start_Capture(SPI_HandleTypeDef *hspi);
/**
* @brief Waits for the capture process to complete in the camera module.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
*/
void Cam_Wait_Capture_Done(SPI_HandleTypeDef *hspi);
/**
* @brief Starts the burst read process from the camera module's FIFO buffer.
* @param hspi Pointer to an SPI_HandleTypeDef structure that contains the configuration information for the specified SPI.
*/
void Cam_Start_Burst_Read(SPI_HandleTypeDef *hspi);

@ -1,3 +1,13 @@
/**
******************************************************************************
* @file : OV5642_regs.h
* @brief : Predefined registers configurations for camera chip.
* This file contains settings for registers to achieve specific camera chip configuration.
* This file was taken over from ArduCam repository and edited to work for this specific project.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
*/
#include "stdint.h"
#include "stdlib.h"
#include "stdio.h"

@ -4,16 +4,11 @@
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
* Code outside of "USER CODE" blocks was generated by STM32CubeMX by STMicroelectronics and was not written by the author.
******************************************************************************
*/
/* USER CODE END Header */
@ -62,6 +57,8 @@ extern "C" {
/* USER CODE END EM */
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
@ -70,28 +67,23 @@ void Error_Handler(void);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
extern I2C_HandleTypeDef hi2c1;
#define MCO_Pin GPIO_PIN_0
#define MCO_GPIO_Port GPIOA
#define DEBUG_LED_Pin GPIO_PIN_1
#define DEBUG_LED_GPIO_Port GPIOA
#define VCP_TX_Pin GPIO_PIN_2
#define VCP_TX_GPIO_Port GPIOA
#define CHIP_SELECT_Pin GPIO_PIN_0
#define CHIP_SELECT_GPIO_Port GPIOB
#define VSET_LED_Pin GPIO_PIN_8
#define VSET_LED_GPIO_Port GPIOA
#define SWDIO_Pin GPIO_PIN_13
#define SWDIO_GPIO_Port GPIOA
#define SWCLK_Pin GPIO_PIN_14
#define SWCLK_GPIO_Port GPIOA
#define VCP_RX_Pin GPIO_PIN_15
#define VCP_RX_GPIO_Port GPIOA
#define LD3_Pin GPIO_PIN_3
#define LD3_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
extern I2C_HandleTypeDef hi2c1;
#define CDC_BUFF_SIZE 51200
#define CDC_FRAME_SIZE 64
#define CDC_FRAME_DELAY 1

@ -76,9 +76,9 @@
#define HAL_SPI_MODULE_ENABLED
/*#define HAL_SRAM_MODULE_ENABLED */
/*#define HAL_SWPMI_MODULE_ENABLED */
/*#define HAL_TIM_MODULE_ENABLED */
#define HAL_TIM_MODULE_ENABLED
/*#define HAL_TSC_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/*#define HAL_UART_MODULE_ENABLED */
/*#define HAL_USART_MODULE_ENABLED */
/*#define HAL_WWDG_MODULE_ENABLED */
/*#define HAL_EXTI_MODULE_ENABLED */

@ -58,7 +58,6 @@ void SysTick_Handler(void);
void DMA1_Channel2_IRQHandler(void);
void DMA1_Channel3_IRQHandler(void);
void SPI1_IRQHandler(void);
void USART2_IRQHandler(void);
void USB_IRQHandler(void);
/* USER CODE BEGIN EFP */

@ -1,4 +1,15 @@
/*
/**
******************************************************************************
* @file : tusb_config.h
* @brief : Configuration file for USB communication.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
* @attention
*
* File was from the large part taken from the TinyUSB repository and just slightly configured for projects usecase.
* Original file contains this disclaimer:
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)

@ -1,6 +1,7 @@
/**
* @file vl53l1_platform.h
* @brief Those platform functions are platform dependent and have to be implemented by the user
* @brief Large portion of this file was taken and edited from the VL53L1 Platform.
* @author Adam Prochazka <xproch0f>
*/
#ifndef _VL53L1_PLATFORM_H_
@ -19,66 +20,74 @@ typedef struct {
typedef VL53L1_Dev_t *VL53L1_DEV;
/** @brief VL53L1_WriteMulti() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_WriteMulti() definition.
*/
int8_t VL53L1_WriteMulti(
uint16_t dev,
uint16_t index,
uint8_t *pdata,
uint32_t count);
/** @brief VL53L1_ReadMulti() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_ReadMulti() definition.
*/
int8_t VL53L1_ReadMulti(
uint16_t dev,
uint16_t index,
uint8_t *pdata,
uint32_t count);
/** @brief VL53L1_WrByte() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_WrByte() definition.
*/
int8_t VL53L1_WrByte(
uint16_t dev,
uint16_t index,
uint8_t data);
/** @brief VL53L1_WrWord() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_WrWord() definition.
*/
int8_t VL53L1_WrWord(
uint16_t dev,
uint16_t index,
uint16_t data);
/** @brief VL53L1_WrDWord() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_WrDWord() definition.
*/
int8_t VL53L1_WrDWord(
uint16_t dev,
uint16_t index,
uint32_t data);
/** @brief VL53L1_RdByte() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_RdByte() definition.
*/
int8_t VL53L1_RdByte(
uint16_t dev,
uint16_t index,
uint8_t *pdata);
/** @brief VL53L1_RdWord() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_RdWord() definition.
*/
int8_t VL53L1_RdWord(
uint16_t dev,
uint16_t index,
uint16_t *pdata);
/** @brief VL53L1_RdDWord() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_RdDWord() definition.
*/
int8_t VL53L1_RdDWord(
uint16_t dev,
uint16_t index,
uint32_t *data);
/** @brief VL53L1_WaitMs() definition.\n
* To be implemented by the developer
/**
* @brief VL53L1_WaitMs() definition.
*/
int8_t VL53L1_WaitMs(
uint16_t dev,

@ -3,15 +3,11 @@
******************************************************************************
* @file : main.c
* @brief : Main program body
* @author : Adam Prochazka <xproch0f>
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
* Code outside of "USER CODE" blocks was generated by STM32CubeMX by STMicroelectronics and was not written by the author.
*
******************************************************************************
*/
@ -40,23 +36,22 @@
/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;
SPI_HandleTypeDef hspi1;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
UART_HandleTypeDef huart2;
TIM_HandleTypeDef htim15;
PCD_HandleTypeDef hpcd_USB_FS;
uint16_t dev=0x52;
/* USER CODE BEGIN PV */
uint16_t DistSensorAddr=0x52;
int status=0;
volatile int IntCount;
#define isInterrupt 1 /* If isInterrupt = 1 then device working in interrupt mode, else device working in polling mode */
/* USER CODE BEGIN PV */
//DAC_HandleTypeDef hdac1;
//TIM_HandleTypeDef htim15;
#define isInterrupt 0 /* If isInterrupt = 1 then device working in interrupt mode, else device working in polling mode */
int SPI_Rx_Done_Flag = 0;
/* USER CODE END PV */
@ -65,14 +60,12 @@ int SPI_Rx_Done_Flag = 0;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_SPI1_Init(void);
static void MX_I2C1_Init(void);
static void MX_USB_PCD_Init(void);
static void MX_TIM15_Init(void);
/* USER CODE BEGIN PFP */
//static void MX_DAC1_Init(void);
//static void MX_TIM15_Init(void);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
@ -86,15 +79,12 @@ static void MX_USB_PCD_Init(void);
int main(void)
{
/* USER CODE BEGIN 1 */
//uint8_t byteData, sensorState=0;
//uint16_t wordData;
//uint8_t ToFSensor = 1; // 0=Left, 1=Center(default), 2=Right
uint16_t Distance = 0;
uint16_t SignalRate;
uint16_t AmbientRate;
uint16_t SpadNum;
uint8_t RangeStatus;
//uint8_t dataReady;
/* USER CODE END 1 */
@ -118,50 +108,58 @@ int main(void)
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_SPI1_Init();
MX_I2C1_Init();
MX_USB_PCD_Init();
MX_TIM15_Init();
/* USER CODE BEGIN 2 */
// Signalize user that device has started
LED_On();
// Enable power to USB, without TinyUSB will not initialize
HAL_PWREx_EnableVddUSB();
// Wait for power to stabilize
HAL_Delay(100);
//ToFSensor = 1; // Select ToFSensor: 0=Left, 1=Center, 2=Right
// Initialize distance sensor
status = VL53L1X_SensorInit(DistSensorAddr);
// Set distance mode of distance sensor for long distance (2)
status = VL53L1X_SetDistanceMode(DistSensorAddr, 2);
status = VL53L1X_SensorInit(dev);
status = VL53L1X_SetDistanceMode(dev, 2);
status = VL53L1X_SetTimingBudgetInMs(dev, 100);
status = VL53L1X_SetInterMeasurementInMs(dev, 100);
status = VL53L1X_StartRanging(dev);
// Set timing budget for each measurement
status = VL53L1X_SetTimingBudgetInMs(DistSensorAddr, 100);
status = VL53L1X_SetInterMeasurementInMs(DistSensorAddr, 100);
// Start first measurement to wake sensor up
status = VL53L1X_StartRanging(DistSensorAddr);
HAL_Delay(1000);
status = VL53L1X_GetRangeStatus(dev, &RangeStatus);
status = VL53L1X_GetDistance(dev, &Distance);
status = VL53L1X_GetSignalRate(dev, &SignalRate);
status = VL53L1X_GetAmbientRate(dev, &AmbientRate);
status = VL53L1X_GetSpadNb(dev, &SpadNum);
status = VL53L1X_ClearInterrupt(dev);
LED_On();
HAL_Delay(1);
// Initialize TinyUSB
tud_init(BOARD_DEVICE_RHPORT_NUM);
HAL_Delay(10);
SPI_Init(&hspi1);
// USB utility function
tud_task();
// Define variables for correct frame sending and capturing
int last_sent_idx = 0;
int buff_stop_idx = 0;
uint16_t image_size = 0;
uint8_t cdc_buff[CDC_BUFF_SIZE+CDC_FRAME_SIZE];
for(int i = 0; i < (CDC_BUFF_SIZE+CDC_FRAME_SIZE); i++) cdc_buff[i] = 0x00;
for(int i = 0; i < (CDC_BUFF_SIZE+CDC_FRAME_SIZE); i++) cdc_buff[i] = 0x00; // Clear frame buffer
//Distance_Sensor_Init(&hi2c1);
int Laser_LED_Switch = 0; // Variable for switching between LASER and LED
// Initial states of LED and LASER (LED off, LASER on)
HAL_GPIO_WritePin(VSET_LED_GPIO_Port, VSET_LED_Pin, GPIO_PIN_RESET);
HAL_TIM_PWM_Start(&htim15, TIM_CHANNEL_1);
// Initialize camera module
Cam_Init(&hi2c1, &hspi1);
/* USER CODE END 2 */
@ -170,41 +168,53 @@ int main(void)
/* USER CODE BEGIN WHILE */
while (1)
{
// USB utility function
tud_task();
// If there wasn't any image captured yet or the last one was sent out completely
if(buff_stop_idx >= (int)image_size){
LED_Off();
// Reset variables responsible for sending correct amount of received image
buff_stop_idx = 0;
last_sent_idx = 0;
//for(int i = 0; i < CDC_BUFF_SIZE; i++) cdc_buff[i] = 0x00;
VL53L1X_GetDistance(dev, &Distance);
HAL_Delay(2);
VL53L1X_ClearInterrupt(dev);
// Get current distance of probe inside the barrel
VL53L1X_GetDistance(DistSensorAddr, &Distance);
CS_Off();
CS_On();
// Start capturing frame and wait until it is done capturing
Cam_Capture(&hspi1);
image_size = Cam_FIFO_length(&hspi1);
Cam_Start_Burst_Read(&hspi1);
// Switch between LASER and LED, so the optical output power of diodes has time to stabilize until next capture
if(Laser_LED_Switch == 1){
Laser_LED_Switch = 0;
__HAL_TIM_SET_COMPARE(&htim15, TIM_CHANNEL_1, 40);
HAL_GPIO_WritePin(VSET_LED_GPIO_Port, VSET_LED_Pin, GPIO_PIN_RESET);
}
else{
Laser_LED_Switch = 1;
__HAL_TIM_SET_COMPARE(&htim15, TIM_CHANNEL_1, 0);
HAL_GPIO_WritePin(VSET_LED_GPIO_Port, VSET_LED_Pin, GPIO_PIN_SET);
}
//getDistance(&hi2c1);
// Get size of captured image, so that correct number of bytec can be read from camera and sent out
image_size = Cam_FIFO_length(&hspi1);
LED_On();
// Activate burst read out mode of camera module (no need for requesting each byte individually)
Cam_Start_Burst_Read(&hspi1);
continue;
}
// Image has not been completely sent out
else {
LED_Off();
// Variable to save number of bytes that should be read from camera module
int number_to_read = 0;
//for(int i = 0; i < CDC_BUFF_SIZE; i++) cdc_buff[i] = 0x00;
// Determine how many bytes should be read from camera module - Is remaining image data to be read larger or smaller than framebuffer?
if((buff_stop_idx + CDC_BUFF_SIZE) > (int) image_size){
number_to_read = (int) image_size - buff_stop_idx;
}
@ -212,35 +222,58 @@ int main(void)
number_to_read = CDC_BUFF_SIZE;
}
// Read determined amount of bytes from camera in blocking mode
HAL_SPI_Receive(&hspi1, cdc_buff, number_to_read, HAL_MAX_DELAY);
// Increment index of already read buffer data
buff_stop_idx = buff_stop_idx + number_to_read;
LED_On();
}
// Variable to store how many bytes were sent during this iteration
int current_sending_idx = 0;
// Inform user that image data transfer started
LED_On();
// Loop to send all image data inside cdc_buff in small CDC chunks
do{
// USB utility function - has to be called between each cdc_write_flush()
tud_task();
// How many bytes should be send in current CDC block
int sendLen = CDC_FRAME_SIZE;
if(last_sent_idx + CDC_FRAME_SIZE > buff_stop_idx){
sendLen = buff_stop_idx - last_sent_idx;
}
// Select bytes, that will be send during next CDC transfer
tud_cdc_write(&cdc_buff[current_sending_idx], sendLen);
// Increment index of data to be sent for next loop iteration
current_sending_idx = current_sending_idx + sendLen;
last_sent_idx = last_sent_idx + sendLen;
// Transfer selected data through CDC
tud_cdc_write_flush();
//Delay between sends
//Delay between sends - necessary for USB synchronization
int i = 0;
for(;i<4000;i++);
}
// Repeat until all data from buffer has been sent
while(last_sent_idx < buff_stop_idx);
// If whole image has been sent, send distance data of where image was captured
if(buff_stop_idx >= (int)image_size){
HAL_Delay(100);
// Delay for synchronization
HAL_Delay(20);
// USB utility function - has to be called, because it wasnt called after last tud_cdc_write_flush()
tud_task();
// Format distance data between predefined header and footer, for clear decoding by receiver
uint8_t distance_buff[12];
distance_buff[0] = 0xff;
distance_buff[1] = 0xff;
@ -255,12 +288,26 @@ int main(void)
distance_buff[10] = '\n';
distance_buff[11] = '\r';
// Prepare to send formatted distance data of image through CDC
tud_cdc_write(&distance_buff[0], 12);
// Necessary delay for synchronization
HAL_Delay(1);
// Transfer prepared Distance data through CDC
tud_cdc_write_flush();
// Necessary delay for synchronization
HAL_Delay(1);
// USB utility function - after write_flush()
tud_task();
}
// Inform user that transfer has been completed
LED_Off();
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
@ -407,37 +454,77 @@ static void MX_SPI1_Init(void)
}
/**
* @brief USART2 Initialization Function
* @brief TIM15 Initialization Function
* @param None
* @retval None
*/
static void MX_USART2_UART_Init(void)
static void MX_TIM15_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE BEGIN TIM15_Init 0 */
/* USER CODE END TIM15_Init 0 */
/* USER CODE END USART2_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE BEGIN TIM15_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
/* USER CODE END TIM15_Init 1 */
htim15.Instance = TIM15;
htim15.Init.Prescaler = 40;
htim15.Init.CounterMode = TIM_COUNTERMODE_UP;
htim15.Init.Period = 1000;
htim15.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim15.Init.RepetitionCounter = 0;
htim15.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim15) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim15, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim15) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim15, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim15, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim15, &sBreakDeadTimeConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE BEGIN TIM15_Init 2 */
/* USER CODE END USART2_Init 2 */
/* USER CODE END TIM15_Init 2 */
HAL_TIM_MspPostInit(&htim15);
}
@ -508,17 +595,17 @@ static void MX_GPIO_Init(void)
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(DEBUG_LED_GPIO_Port, DEBUG_LED_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOA, DEBUG_LED_Pin|VSET_LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, CHIP_SELECT_Pin|LD3_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : DEBUG_LED_Pin */
GPIO_InitStruct.Pin = DEBUG_LED_Pin;
/*Configure GPIO pins : DEBUG_LED_Pin VSET_LED_Pin */
GPIO_InitStruct.Pin = DEBUG_LED_Pin|VSET_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DEBUG_LED_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : CHIP_SELECT_Pin LD3_Pin */
GPIO_InitStruct.Pin = CHIP_SELECT_Pin|LD3_Pin;
@ -535,11 +622,6 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
SPI_Rx_Done_Flag = 1;
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
// do nothing here
}
/* USER CODE END 4 */
/**

@ -60,7 +60,9 @@ extern DMA_HandleTypeDef hdma_spi1_tx;
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
@ -268,89 +270,71 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
}
/**
* @brief UART MSP Initialization
* @brief TIM_Base MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
if(huart->Instance==USART2)
if(htim_base->Instance==TIM15)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE BEGIN TIM15_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* USER CODE END TIM15_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM15_CLK_ENABLE();
/* USER CODE BEGIN TIM15_MspInit 1 */
/** Initializes the peripherals clock
*/
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART2;
PeriphClkInit.Usart2ClockSelection = RCC_USART2CLKSOURCE_PCLK1;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END TIM15_MspInit 1 */
}
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM15)
{
/* USER CODE BEGIN TIM15_MspPostInit 0 */
/* USER CODE END TIM15_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA15 (JTDI) ------> USART2_RX
/**TIM15 GPIO Configuration
PA2 ------> TIM15_CH1
*/
GPIO_InitStruct.Pin = VCP_TX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(VCP_TX_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = VCP_RX_Pin;
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF3_USART2;
HAL_GPIO_Init(VCP_RX_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF14_TIM15;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART2 interrupt Init */
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspInit 1 */
/* USER CODE BEGIN TIM15_MspPostInit 1 */
/* USER CODE END USART2_MspInit 1 */
/* USER CODE END TIM15_MspPostInit 1 */
}
}
/**
* @brief UART MSP De-Initialization
* @brief TIM_Base MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
if(huart->Instance==USART2)
if(htim_base->Instance==TIM15)
{
/* USER CODE BEGIN USART2_MspDeInit 0 */
/* USER CODE BEGIN TIM15_MspDeInit 0 */
/* USER CODE END USART2_MspDeInit 0 */
/* USER CODE END TIM15_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA15 (JTDI) ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOA, VCP_TX_Pin|VCP_RX_Pin);
/* USART2 interrupt DeInit */
HAL_NVIC_DisableIRQ(USART2_IRQn);
/* USER CODE BEGIN USART2_MspDeInit 1 */
__HAL_RCC_TIM15_CLK_DISABLE();
/* USER CODE BEGIN TIM15_MspDeInit 1 */
/* USER CODE END USART2_MspDeInit 1 */
/* USER CODE END TIM15_MspDeInit 1 */
}
}

@ -58,7 +58,6 @@
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx;
extern SPI_HandleTypeDef hspi1;
extern UART_HandleTypeDef huart2;
extern PCD_HandleTypeDef hpcd_USB_FS;
/* USER CODE BEGIN EV */
@ -244,20 +243,6 @@ void SPI1_IRQHandler(void)
/* USER CODE END SPI1_IRQn 1 */
}
/**
* @brief This function handles USART2 global interrupt.
*/
void USART2_IRQHandler(void)
{
/* USER CODE BEGIN USART2_IRQn 0 */
/* USER CODE END USART2_IRQn 0 */
HAL_UART_IRQHandler(&huart2);
/* USER CODE BEGIN USART2_IRQn 1 */
/* USER CODE END USART2_IRQn 1 */
}
/**
* @brief This function handles USB event interrupt through EXTI line 17.
*/

@ -1,4 +1,15 @@
/*
/**
******************************************************************************
* @file : usb_descriptors.c
* @brief : Descriptors of usb communication.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
* @attention
*
* File was from the large part taken from the TinyUSB repository and just slightly configured for projects usecase.
* Original file contains this disclaimer:
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
@ -216,11 +227,11 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
// array of pointer to string descriptors
char const* string_desc_arr [] =
{
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"TinyUSB", // 1: Manufacturer
"TinyUSB test STM32L432", // 2: Product
"123456", // 3: Serials, should use chip ID
"TinyUSB CDC", // 4: CDC Interface
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"Adam Prochazka", // 1: Manufacturer
"Profilometer Probe", // 2: Product
"2023", // 3: Serials, should use chip ID
"TinyUSB CDC", // 4: CDC Interface
};
static uint16_t _desc_str[32];

@ -1,5 +1,15 @@
/*
/**
******************************************************************************
* @file : vl53l1_platform.c
* @brief : Platform specific configuration of distance sencor communication.
* @author : Adam Prochazka <xproch0f>
******************************************************************************
* @attention
* File was partly taken from the VL53L1 Platform and configured for NucleoL432KC platform.
* Configuration consisted mainly of implementing basic I2C communication functions, that were specific for this project.
* Original file contains this disclaimer:
*
* This file is part of VL53L1 Platform
*
* Copyright (c) 2016, STMicroelectronics - All Rights Reserved
@ -36,7 +46,6 @@
#include "vl53l1_platform.h"
#include "vl53l1_platform_log.h"
//#include "vl53l1_api.h"
#include "vl53l1_platform_user_config.h"
#include "stm32xxx_hal.h"
#include "main.h"
@ -44,7 +53,6 @@
#include <time.h>
#include <math.h>
#include "vl53l1_error_codes.h"
//#include "X-NUCLEO-53L1A1.h"
#define I2C_TIME_OUT_BASE 10
@ -78,25 +86,16 @@ uint8_t _I2CBuffer[256];
int _I2CWrite(uint16_t Dev, uint8_t *pdata, uint32_t count) {
int status;
//int i2c_time_out = I2C_TIME_OUT_BASE+ count* I2C_TIME_OUT_BYTE;
status = HAL_I2C_Master_Transmit(&hi2c1, Dev, pdata, count, HAL_MAX_DELAY);
if (status) {
//VL6180x_ErrLog("I2C error 0x%x %d len", dev->I2cAddr, len);
//XNUCLEO6180XA1_I2C1_Init(&hi2c1);
}
return status;
}
int _I2CRead(uint16_t Dev, uint8_t *pdata, uint32_t count) {
int status;
//int i2c_time_out = I2C_TIME_OUT_BASE+ count* I2C_TIME_OUT_BYTE;
status = HAL_I2C_Master_Receive(&hi2c1, Dev|1, pdata, count, HAL_MAX_DELAY);
if (status) {
//VL6180x_ErrLog("I2C error 0x%x %d len", dev->I2cAddr, len);
//XNUCLEO6180XA1_I2C1_Init(&hi2c1);
}
return status;
}

@ -1,743 +0,0 @@
/**
******************************************************************************
* @file stm32l4xx_hal_uart_ex.h
* @author MCD Application Team
* @brief Header file of UART HAL Extended module.
******************************************************************************
* @attention
*
* Copyright (c) 2017 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef STM32L4xx_HAL_UART_EX_H
#define STM32L4xx_HAL_UART_EX_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32l4xx_hal_def.h"
/** @addtogroup STM32L4xx_HAL_Driver
* @{
*/
/** @addtogroup UARTEx
* @{
*/
/* Exported types ------------------------------------------------------------*/
/** @defgroup UARTEx_Exported_Types UARTEx Exported Types
* @{
*/
/**
* @brief UART wake up from stop mode parameters
*/
typedef struct
{
uint32_t WakeUpEvent; /*!< Specifies which event will activate the Wakeup from Stop mode flag (WUF).
This parameter can be a value of @ref UART_WakeUp_from_Stop_Selection.
If set to UART_WAKEUP_ON_ADDRESS, the two other fields below must
be filled up. */
uint16_t AddressLength; /*!< Specifies whether the address is 4 or 7-bit long.
This parameter can be a value of @ref UARTEx_WakeUp_Address_Length. */
uint8_t Address; /*!< UART/USART node address (7-bit long max). */
} UART_WakeUpTypeDef;
/**
* @}
*/
/* Exported constants --------------------------------------------------------*/
/** @defgroup UARTEx_Exported_Constants UARTEx Exported Constants
* @{
*/
/** @defgroup UARTEx_Word_Length UARTEx Word Length
* @{
*/
#define UART_WORDLENGTH_7B USART_CR1_M1 /*!< 7-bit long UART frame */
#define UART_WORDLENGTH_8B 0x00000000U /*!< 8-bit long UART frame */
#define UART_WORDLENGTH_9B USART_CR1_M0 /*!< 9-bit long UART frame */
/**
* @}
*/
/** @defgroup UARTEx_WakeUp_Address_Length UARTEx WakeUp Address Length
* @{
*/
#define UART_ADDRESS_DETECT_4B 0x00000000U /*!< 4-bit long wake-up address */
#define UART_ADDRESS_DETECT_7B USART_CR2_ADDM7 /*!< 7-bit long wake-up address */
/**
* @}
*/
#if defined(USART_CR1_FIFOEN)
/** @defgroup UARTEx_FIFO_mode UARTEx FIFO mode
* @brief UART FIFO mode
* @{
*/
#define UART_FIFOMODE_DISABLE 0x00000000U /*!< FIFO mode disable */
#define UART_FIFOMODE_ENABLE USART_CR1_FIFOEN /*!< FIFO mode enable */
/**
* @}
*/
/** @defgroup UARTEx_TXFIFO_threshold_level UARTEx TXFIFO threshold level
* @brief UART TXFIFO threshold level
* @{
*/
#define UART_TXFIFO_THRESHOLD_1_8 0x00000000U /*!< TX FIFO reaches 1/8 of its depth */
#define UART_TXFIFO_THRESHOLD_1_4 USART_CR3_TXFTCFG_0 /*!< TX FIFO reaches 1/4 of its depth */
#define UART_TXFIFO_THRESHOLD_1_2 USART_CR3_TXFTCFG_1 /*!< TX FIFO reaches 1/2 of its depth */
#define UART_TXFIFO_THRESHOLD_3_4 (USART_CR3_TXFTCFG_0|USART_CR3_TXFTCFG_1) /*!< TX FIFO reaches 3/4 of its depth */
#define UART_TXFIFO_THRESHOLD_7_8 USART_CR3_TXFTCFG_2 /*!< TX FIFO reaches 7/8 of its depth */
#define UART_TXFIFO_THRESHOLD_8_8 (USART_CR3_TXFTCFG_2|USART_CR3_TXFTCFG_0) /*!< TX FIFO becomes empty */
/**
* @}
*/
/** @defgroup UARTEx_RXFIFO_threshold_level UARTEx RXFIFO threshold level
* @brief UART RXFIFO threshold level
* @{
*/
#define UART_RXFIFO_THRESHOLD_1_8 0x00000000U /*!< RX FIFO reaches 1/8 of its depth */
#define UART_RXFIFO_THRESHOLD_1_4 USART_CR3_RXFTCFG_0 /*!< RX FIFO reaches 1/4 of its depth */
#define UART_RXFIFO_THRESHOLD_1_2 USART_CR3_RXFTCFG_1 /*!< RX FIFO reaches 1/2 of its depth */
#define UART_RXFIFO_THRESHOLD_3_4 (USART_CR3_RXFTCFG_0|USART_CR3_RXFTCFG_1) /*!< RX FIFO reaches 3/4 of its depth */
#define UART_RXFIFO_THRESHOLD_7_8 USART_CR3_RXFTCFG_2 /*!< RX FIFO reaches 7/8 of its depth */
#define UART_RXFIFO_THRESHOLD_8_8 (USART_CR3_RXFTCFG_2|USART_CR3_RXFTCFG_0) /*!< RX FIFO becomes full */
/**
* @}
*/
#endif /* USART_CR1_FIFOEN */
/**
* @}
*/
/* Exported macros -----------------------------------------------------------*/
/* Exported functions --------------------------------------------------------*/
/** @addtogroup UARTEx_Exported_Functions
* @{
*/
/** @addtogroup UARTEx_Exported_Functions_Group1
* @{
*/
/* Initialization and de-initialization functions ****************************/
HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime,
uint32_t DeassertionTime);
/**
* @}
*/
/** @addtogroup UARTEx_Exported_Functions_Group2
* @{
*/
void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart);
#if defined(USART_CR1_FIFOEN)
void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart);
void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart);
#endif /* USART_CR1_FIFOEN */
/**
* @}
*/
/** @addtogroup UARTEx_Exported_Functions_Group3
* @{
*/
/* Peripheral Control functions **********************************************/
HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection);
HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart);
#if defined(USART_CR3_UCESM)
HAL_StatusTypeDef HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef *huart);
#endif /* USART_CR3_UCESM */
HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength);
#if defined(USART_CR1_FIFOEN)
HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart);
HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold);
HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold);
#endif /* USART_CR1_FIFOEN */
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
uint32_t Timeout);
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size);
/**
* @}
*/
/**
* @}
*/
/* Private macros ------------------------------------------------------------*/
/** @defgroup UARTEx_Private_Macros UARTEx Private Macros
* @{
*/
/** @brief Report the UART clock source.
* @param __HANDLE__ specifies the UART Handle.
* @param __CLOCKSOURCE__ output variable.
* @retval UART clocking source, written in __CLOCKSOURCE__.
*/
#if defined (STM32L471xx) || defined (STM32L475xx) || defined (STM32L476xx) || defined (STM32L485xx) || defined (STM32L486xx) \
|| defined (STM32L496xx) || defined (STM32L4A6xx) \
|| defined (STM32L4P5xx) || defined (STM32L4Q5xx) \
|| defined (STM32L4R5xx) || defined (STM32L4R7xx) || defined (STM32L4R9xx) || defined (STM32L4S5xx) || defined (STM32L4S7xx) || defined (STM32L4S9xx)
#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \
do { \
if((__HANDLE__)->Instance == USART1) \
{ \
switch(__HAL_RCC_GET_USART1_SOURCE()) \
{ \
case RCC_USART1CLKSOURCE_PCLK2: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \
break; \
case RCC_USART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART2) \
{ \
switch(__HAL_RCC_GET_USART2_SOURCE()) \
{ \
case RCC_USART2CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART2CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART2CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART2CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART3) \
{ \
switch(__HAL_RCC_GET_USART3_SOURCE()) \
{ \
case RCC_USART3CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART3CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART3CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART3CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == UART4) \
{ \
switch(__HAL_RCC_GET_UART4_SOURCE()) \
{ \
case RCC_UART4CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_UART4CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_UART4CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_UART4CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == UART5) \
{ \
switch(__HAL_RCC_GET_UART5_SOURCE()) \
{ \
case RCC_UART5CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_UART5CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_UART5CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_UART5CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == LPUART1) \
{ \
switch(__HAL_RCC_GET_LPUART1_SOURCE()) \
{ \
case RCC_LPUART1CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_LPUART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_LPUART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_LPUART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else \
{ \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
} \
} while(0U)
#elif defined (STM32L412xx) || defined (STM32L422xx) \
|| defined (STM32L431xx) || defined (STM32L433xx) || defined (STM32L443xx)
#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \
do { \
if((__HANDLE__)->Instance == USART1) \
{ \
switch(__HAL_RCC_GET_USART1_SOURCE()) \
{ \
case RCC_USART1CLKSOURCE_PCLK2: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \
break; \
case RCC_USART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART2) \
{ \
switch(__HAL_RCC_GET_USART2_SOURCE()) \
{ \
case RCC_USART2CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART2CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART2CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART2CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART3) \
{ \
switch(__HAL_RCC_GET_USART3_SOURCE()) \
{ \
case RCC_USART3CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART3CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART3CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART3CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == LPUART1) \
{ \
switch(__HAL_RCC_GET_LPUART1_SOURCE()) \
{ \
case RCC_LPUART1CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_LPUART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_LPUART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_LPUART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else \
{ \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
} \
} while(0U)
#elif defined (STM32L432xx) || defined (STM32L442xx)
#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \
do { \
if((__HANDLE__)->Instance == USART1) \
{ \
switch(__HAL_RCC_GET_USART1_SOURCE()) \
{ \
case RCC_USART1CLKSOURCE_PCLK2: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \
break; \
case RCC_USART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART2) \
{ \
switch(__HAL_RCC_GET_USART2_SOURCE()) \
{ \
case RCC_USART2CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART2CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART2CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART2CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == LPUART1) \
{ \
switch(__HAL_RCC_GET_LPUART1_SOURCE()) \
{ \
case RCC_LPUART1CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_LPUART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_LPUART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_LPUART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else \
{ \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
} \
} while(0U)
#elif defined (STM32L451xx) || defined (STM32L452xx) || defined (STM32L462xx)
#define UART_GETCLOCKSOURCE(__HANDLE__,__CLOCKSOURCE__) \
do { \
if((__HANDLE__)->Instance == USART1) \
{ \
switch(__HAL_RCC_GET_USART1_SOURCE()) \
{ \
case RCC_USART1CLKSOURCE_PCLK2: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK2; \
break; \
case RCC_USART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART2) \
{ \
switch(__HAL_RCC_GET_USART2_SOURCE()) \
{ \
case RCC_USART2CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART2CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART2CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART2CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == USART3) \
{ \
switch(__HAL_RCC_GET_USART3_SOURCE()) \
{ \
case RCC_USART3CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_USART3CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_USART3CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_USART3CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == UART4) \
{ \
switch(__HAL_RCC_GET_UART4_SOURCE()) \
{ \
case RCC_UART4CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_UART4CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_UART4CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_UART4CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else if((__HANDLE__)->Instance == LPUART1) \
{ \
switch(__HAL_RCC_GET_LPUART1_SOURCE()) \
{ \
case RCC_LPUART1CLKSOURCE_PCLK1: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_PCLK1; \
break; \
case RCC_LPUART1CLKSOURCE_HSI: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_HSI; \
break; \
case RCC_LPUART1CLKSOURCE_SYSCLK: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_SYSCLK; \
break; \
case RCC_LPUART1CLKSOURCE_LSE: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_LSE; \
break; \
default: \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
break; \
} \
} \
else \
{ \
(__CLOCKSOURCE__) = UART_CLOCKSOURCE_UNDEFINED; \
} \
} while(0U)
#endif /* STM32L471xx || STM32L475xx || STM32L476xx || STM32L485xx || STM32L486xx ||
* STM32L496xx || STM32L4A6xx ||
* STM32L4P5xx || STM32L4Q5xx ||
* STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx
*/
/** @brief Report the UART mask to apply to retrieve the received data
* according to the word length and to the parity bits activation.
* @note If PCE = 1, the parity bit is not included in the data extracted
* by the reception API().
* This masking operation is not carried out in the case of
* DMA transfers.
* @param __HANDLE__ specifies the UART Handle.
* @retval None, the mask to apply to UART RDR register is stored in (__HANDLE__)->Mask field.
*/
#define UART_MASK_COMPUTATION(__HANDLE__) \
do { \
if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_9B) \
{ \
if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \
{ \
(__HANDLE__)->Mask = 0x01FFU ; \
} \
else \
{ \
(__HANDLE__)->Mask = 0x00FFU ; \
} \
} \
else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_8B) \
{ \
if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \
{ \
(__HANDLE__)->Mask = 0x00FFU ; \
} \
else \
{ \
(__HANDLE__)->Mask = 0x007FU ; \
} \
} \
else if ((__HANDLE__)->Init.WordLength == UART_WORDLENGTH_7B) \
{ \
if ((__HANDLE__)->Init.Parity == UART_PARITY_NONE) \
{ \
(__HANDLE__)->Mask = 0x007FU ; \
} \
else \
{ \
(__HANDLE__)->Mask = 0x003FU ; \
} \
} \
else \
{ \
(__HANDLE__)->Mask = 0x0000U; \
} \
} while(0U)
/**
* @brief Ensure that UART frame length is valid.
* @param __LENGTH__ UART frame length.
* @retval SET (__LENGTH__ is valid) or RESET (__LENGTH__ is invalid)
*/
#define IS_UART_WORD_LENGTH(__LENGTH__) (((__LENGTH__) == UART_WORDLENGTH_7B) || \
((__LENGTH__) == UART_WORDLENGTH_8B) || \
((__LENGTH__) == UART_WORDLENGTH_9B))
/**
* @brief Ensure that UART wake-up address length is valid.
* @param __ADDRESS__ UART wake-up address length.
* @retval SET (__ADDRESS__ is valid) or RESET (__ADDRESS__ is invalid)
*/
#define IS_UART_ADDRESSLENGTH_DETECT(__ADDRESS__) (((__ADDRESS__) == UART_ADDRESS_DETECT_4B) || \
((__ADDRESS__) == UART_ADDRESS_DETECT_7B))
#if defined(USART_CR1_FIFOEN)
/**
* @brief Ensure that UART TXFIFO threshold level is valid.
* @param __THRESHOLD__ UART TXFIFO threshold level.
* @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid)
*/
#define IS_UART_TXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_8) || \
((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_4) || \
((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_1_2) || \
((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_3_4) || \
((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_7_8) || \
((__THRESHOLD__) == UART_TXFIFO_THRESHOLD_8_8))
/**
* @brief Ensure that UART RXFIFO threshold level is valid.
* @param __THRESHOLD__ UART RXFIFO threshold level.
* @retval SET (__THRESHOLD__ is valid) or RESET (__THRESHOLD__ is invalid)
*/
#define IS_UART_RXFIFO_THRESHOLD(__THRESHOLD__) (((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_8) || \
((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_4) || \
((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_1_2) || \
((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_3_4) || \
((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_7_8) || \
((__THRESHOLD__) == UART_RXFIFO_THRESHOLD_8_8))
#endif /* USART_CR1_FIFOEN */
/**
* @}
*/
/* Private functions ---------------------------------------------------------*/
/**
* @}
*/
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* STM32L4xx_HAL_UART_EX_H */

File diff suppressed because it is too large Load Diff

@ -35,21 +35,22 @@ Mcu.IP2=NVIC
Mcu.IP3=RCC
Mcu.IP4=SPI1
Mcu.IP5=SYS
Mcu.IP6=USART2
Mcu.IP6=TIM15
Mcu.IP7=USB
Mcu.IPNb=8
Mcu.Name=STM32L432K(B-C)Ux
Mcu.Package=UFQFPN32
Mcu.Pin0=PC14-OSC32_IN (PC14)
Mcu.Pin1=PC15-OSC32_OUT (PC15)
Mcu.Pin10=PA10
Mcu.Pin11=PA11
Mcu.Pin12=PA12
Mcu.Pin13=PA13 (JTMS-SWDIO)
Mcu.Pin14=PA14 (JTCK-SWCLK)
Mcu.Pin15=PA15 (JTDI)
Mcu.Pin10=PA9
Mcu.Pin11=PA10
Mcu.Pin12=PA11
Mcu.Pin13=PA12
Mcu.Pin14=PA13 (JTMS-SWDIO)
Mcu.Pin15=PA14 (JTCK-SWCLK)
Mcu.Pin16=PB3 (JTDO-TRACESWO)
Mcu.Pin17=VP_SYS_VS_Systick
Mcu.Pin18=VP_TIM15_VS_ClockSourceINT
Mcu.Pin2=PA0
Mcu.Pin3=PA1
Mcu.Pin4=PA2
@ -57,8 +58,8 @@ Mcu.Pin5=PA5
Mcu.Pin6=PA6
Mcu.Pin7=PA7
Mcu.Pin8=PB0
Mcu.Pin9=PA9
Mcu.PinsNb=18
Mcu.Pin9=PA8
Mcu.PinsNb=19
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32L432KCUx
@ -77,7 +78,6 @@ NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SPI1_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:true\:true\:true\:false
NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.USB_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA0.GPIOParameters=GPIO_Label
@ -105,16 +105,8 @@ PA14\ (JTCK-SWCLK).GPIO_Label=SWCLK
PA14\ (JTCK-SWCLK).Locked=true
PA14\ (JTCK-SWCLK).Mode=Serial_Wire
PA14\ (JTCK-SWCLK).Signal=SYS_JTCK-SWCLK
PA15\ (JTDI).GPIOParameters=GPIO_Label
PA15\ (JTDI).GPIO_Label=VCP_RX
PA15\ (JTDI).Locked=true
PA15\ (JTDI).Mode=Asynchronous
PA15\ (JTDI).Signal=USART2_RX
PA2.GPIOParameters=GPIO_Label
PA2.GPIO_Label=VCP_TX
PA2.Locked=true
PA2.Mode=Asynchronous
PA2.Signal=USART2_TX
PA2.Signal=S_TIM15_CH1
PA5.Locked=true
PA5.Mode=Full_Duplex_Master
PA5.Signal=SPI1_SCK
@ -122,6 +114,10 @@ PA6.Mode=Full_Duplex_Master
PA6.Signal=SPI1_MISO
PA7.Mode=Full_Duplex_Master
PA7.Signal=SPI1_MOSI
PA8.GPIOParameters=GPIO_Label
PA8.GPIO_Label=VSET_LED
PA8.Locked=true
PA8.Signal=GPIO_Output
PA9.Mode=I2C
PA9.Signal=I2C1_SCL
PB0.GPIOParameters=GPIO_Label
@ -167,7 +163,7 @@ ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=Makefile
ProjectManager.ToolChainLocation=
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_USART2_UART_Init-USART2-false-HAL-true,5-MX_SPI1_Init-SPI1-false-HAL-true,6-MX_I2C1_Init-I2C1-false-HAL-true,7-MX_USB_PCD_Init-USB-false-HAL-true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_I2C1_Init-I2C1-false-HAL-true,6-MX_USB_PCD_Init-USB-false-HAL-true
RCC.48CLKFreq_Value=24000000
RCC.ADCFreq_Value=64000000
RCC.AHBFreq_Value=80000000
@ -227,6 +223,8 @@ RCC.VCOInputFreq_Value=16000000
RCC.VCOOutputFreq_Value=160000000
RCC.VCOSAI1OutputFreq_Value=128000000
RCC.WatchDogFreq_Value=32000
SH.S_TIM15_CH1.0=TIM15_CH1,PWM Generation1 CH1
SH.S_TIM15_CH1.ConfNb=1
SPI1.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_32
SPI1.CalculateBaudRate=2.5 MBits/s
SPI1.DataSize=SPI_DATASIZE_8BIT
@ -235,9 +233,14 @@ SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRate
SPI1.Mode=SPI_MODE_MASTER
SPI1.NSSPMode=SPI_NSS_PULSE_DISABLE
SPI1.VirtualType=VM_MASTER
USART2.IPParameters=VirtualMode-Asynchronous
USART2.VirtualMode-Asynchronous=VM_ASYNC
TIM15.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM15.IPParameters=Channel-PWM Generation1 CH1,Prescaler,Pulse-PWM Generation1 CH1,Period
TIM15.Period=1000
TIM15.Prescaler=40
TIM15.Pulse-PWM\ Generation1\ CH1=500
VP_SYS_VS_Systick.Mode=SysTick
VP_SYS_VS_Systick.Signal=SYS_VS_Systick
VP_TIM15_VS_ClockSourceINT.Mode=Internal
VP_TIM15_VS_ClockSourceINT.Signal=TIM15_VS_ClockSourceINT
board=NUCLEO-L432KC
boardIOC=true

@ -4505,6 +4505,7 @@
(xy 56.678023 90.855289)
(xy 56.727368 90.850972)
(xy 56.738176 90.8505)
(xy 56.743709 90.8505)
(xy 80.63777 90.8505)
(xy 80.685223 90.859939)
(xy 80.725451 90.886819)

@ -1,6 +1,6 @@
{
"board": {
"active_layer": 0,
"active_layer": 36,
"active_layer_preset": "All Layers",
"auto_track_width": true,
"hidden_netclasses": [],

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

@ -1,54 +1,60 @@
# Profilometer Probe
## Firmware for profilometer probe
### Build
- Build using Makefile inside Firmware folder
- Flash onto hardware using flash option for make command `$ make flash`
![alt text](https://github.com/aprochazka/ProfilometerProbe/blob/main/Probe_Render.png?raw=true)
![alt text](https://github.com/aprochazka/ProfilometerProbe/blob/main/Probe_Assembled.png?raw=true)
### Supported HW:
- Nucleo L432KC
- Arducam 5MP Plus
## Hardware
### Models
### HW Setup
- All 3D printable models are located inside Models folder
- Models are designed to be printed with standard 2mm layer height
- When slicing be sure to print outer walls first to make print more accurate
Before running code, connect camera module to microcontroler through pins described in .ioc file (open with STM32CubeMX) or in table below.
### Components
| Name | Nucleo L432KC | Arducam 5MP Plus |
| ----------- | ------------- | ---------------- |
| SPI SCLK | A4 | SCK |
| SPI MISO | A5 | MISO |
| SPI MOSI | A6 | MOSI |
| SPI CS | D3 | CS |
| I2C SCL | D1 | SCL |
| I2C SDA | D0 | SDA |
- Development board: Nucleo L432KC
- Camera: ArduCam mini 5MP Plus
- Distance sensor: Pimoroni LV53L1X
- Complete list of components and connectors for probe can be found inside HW/Parts.md
You can connect optional Debug LED to A1 pin in Nucleo board.
## Firmware for profilometer probe
#### Probe design block Scheme
![alt text](https://github.com/aprochazka/ProfilometerProbe/blob/main/deviceScheme.png?raw=true)
### Current State
### Build
- Build using Makefile inside Firmware folder (dependency: arm-none-eabi)
- Flash onto hardware using flash option for make command `$ make flash`
### Usage
- Sends test JPEG image sequence through USB CDC
- Connect probe to pc using usb c cable and firmware will start sending sending data automatically
### Test Current State
### Documentation
- Tested on: Arch Linux
- Create documentation using 'doc' option of Makefile '$ make doc'
## Software for receiving data
### Build
- Inside Receiver folder build using Makefile
- Build using Makefile inside Receiver folder
- Code counts with CDC device on /dev/ttyACM2 (can be changed in code)
### Usage
- Run with sudo permission, so that serial port is openable
- Has to be run with sudo permissions to correctly access USB CDC port.
- '$ sudo ./main -p <name of the port> [-s Save received jpeg to files] [-r Print raw received CDC data to standard output]'
- Prefer running with optional -s command for ability to inspect already captured images
### Test Script Usage - outdated
### Documentation
- Build test app using provided Makefile and then run the executable
- Create documentation using 'doc' option of Makefile '$ make doc'
- App will then start saving files received by uart to filesystem
### TODO
### In progress
- Process image and filter only laser line from it
- Use precessed data to determine depth or height of irregularities

@ -58,6 +58,7 @@
"stop_token": "cpp",
"streambuf": "cpp",
"cinttypes": "cpp",
"typeinfo": "cpp"
"typeinfo": "cpp",
"fstream": "cpp"
}
}

@ -1,3 +1,12 @@
/**
* @file Displayer.cpp
* @brief Source file for the Displayer class.
* @author Adam Prochazka <xproch0f>
*
* This file contains the implementation of the Displayer class which is responsible for
* rendering the images received from the Receiver class.
*/
#include "main.hpp"
#include "Displayer.hpp"
@ -8,10 +17,9 @@ int Displayer::createWindow() {
return 1;
}
window = SDL_CreateWindow("Image Viewer", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_SHOWN);
window = SDL_CreateWindow("Profilometer View", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1920, 1080, SDL_WINDOW_SHOWN);
if (!window) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create window: %s", SDL_GetError());
//SDL_Quit();
return 1;
}
@ -23,18 +31,15 @@ int Displayer::renderWindow(){
if (!renderer) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to create renderer: %s", SDL_GetError());
//SDL_DestroyWindow(window);
//SDL_Quit();
return 1;
}
return 0;
}
#define PRINT_BUFFER 0
int Displayer::imageFromVector(std::vector<uint8_t>* img){
#if PRINT_BUFFER
int Displayer::imageFromVector(std::vector<uint8_t>* img, bool printRaw){
if(printRaw){
std::cout << "______________" << std::endl;
for(int i = 0; i<(int)(img)->size(); i++)
@ -44,7 +49,7 @@ int Displayer::imageFromVector(std::vector<uint8_t>* img){
std::cout << std::endl;
std::cout << "______________" << std::endl;
#endif
}
imageRwops = SDL_RWFromMem(img->data(), img->size());
return 0;
@ -52,12 +57,10 @@ int Displayer::imageFromVector(std::vector<uint8_t>* img){
int Displayer::createImageSurface(){
imageSurface = IMG_Load_RW(imageRwops, 0);
if (!imageSurface) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load image: %s", IMG_GetError());
//SDL_DestroyRenderer(renderer);
//SDL_DestroyWindow(window);
//SDL_Quit();
//return 1;
return 1;
}
return 0;
@ -106,13 +109,12 @@ int Displayer::windowDestroy(){
return 0;
}
int Displayer::windowLoop(){
bool quit = false;
while (!quit) {
int Displayer::windowLoop(bool *q){
while (!(*q)) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
quit = true;
*q = true;
}
}
@ -145,8 +147,8 @@ int Displayer::windowLoop(){
}
int Displayer::vectorToTexture(std::vector<uint8_t>* img){
imageFromVector(img);
int Displayer::vectorToTexture(std::vector<uint8_t>* img, bool printRaw){
imageFromVector(img, printRaw);
createImageSurface();
textureFromSurface();
@ -165,5 +167,6 @@ int Displayer::flipThroughTextures(){
flipIdx++;
flipIdx%=2;
}
return 0;
}

@ -1,5 +1,19 @@
/**
* @file Displayer.hpp
* @brief Header file for the Displayer class.
* @author Adam Prochazka <xproch0f>
*
* This file contains the declaration of the Displayer class which is responsible for
* rendering the images received from the Receiver class.
*/
#include "main.hpp"
#define DISPLAYER_HPP
/*!
* \class Displayer
* \brief This class is responsible for displaying image data to user, that includes storing image bytes inside buffer, creating textures from those bytes, rendering UI and updating UI.
*/
class Displayer {
private:
SDL_Window* window;
@ -16,19 +30,63 @@ class Displayer {
std::mutex currentTextureIndexMutex;
public:
/*!
* \brief Create the main SDL window.
* \return 0 on success, 1 on failure.
*/
int createWindow();
/*!
* \brief Render the main SDL window.
* \return 0 on success, 1 on failure.
*/
int renderWindow();
int imageFromVector(std::vector<uint8_t>* img);
/*!
* \brief Copy image data from a vector to an SDL_RWops structure.
* \param[in] img A pointer to the vector containing the image data.
* @param printRaw Bool that indicates weather received byte data should be printed to std::out (for debug).
* \return 0.
*/
int imageFromVector(std::vector<uint8_t>* img, bool printRaw = false);
/*!
* \brief Create an SDL_Surface from the SDL_RWops structure containing image data.
* \return 0 on success, 1 on failure.
*/
int createImageSurface();
/*!
* \brief Create an SDL_Texture from an SDL_Surface and store it to last recently used texture buffer.
* \return 0 on success, 1 on failure.
*/
int textureFromSurface();
int vectorToTexture(std::vector<uint8_t>* img);
/*!
* \brief Convert a vector of image data to an SDL_Texture and store it to laset recently used texture buffer.
* \param[in] img A pointer to the vector containing the image data.
* @param printRaw Bool that indicates weather received byte data should be printed to std::out (for debug).
* \return 0.
*/
int vectorToTexture(std::vector<uint8_t>* img, bool printRaw = false);
/*!
* \brief Destroy the main SDL window, SDL renderer and SDL textures stored in buffers.
* \return 0 on success, 1 on failure.
*/
int windowDestroy();
int windowLoop();
/*!
* \brief Run the main window loop, refresh currently rendered texture buffer with newest one from texture buffers.
* \return 0.
*/
int windowLoop(bool *q);
/*!
* \brief Test function to see if rendering works by infinitelly flipping between two predefined textures.
* \return 0.
*/
int flipThroughTextures();
};

File diff suppressed because it is too large Load Diff

@ -7,6 +7,9 @@ OBJS = $(SRCS:.cpp=.o)
all: main
doc:
doxygen
main: $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o main $(LDLIBS)
@ -14,4 +17,4 @@ main: $(OBJS)
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) main
rm -rf $(OBJS) main doc

@ -1,3 +1,12 @@
/**
* @file Receiver.cpp
* @brief Source file for the Receiver class.
* @author Adam Prochazka <xproch0f>
*
* This file contains the implementation of the Receiver class which is responsible for
* managing the serial communication and processing the received data to display images.
*/
#include "Receiver.hpp"
Receiver::Receiver(Displayer *displayerPtr){
@ -8,10 +17,10 @@ void Receiver::printHex(unsigned char value) {
std::cout << "0x" << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>(value);
}
void Receiver::openStream(){
void Receiver::openStream(char * port){
while(1){
// Open the CDC device file for reading
cdcFile = open("/dev/ttyACM1", O_RDWR | O_NOCTTY);
// Open the CDC device file for reading
cdcFile = open(port, O_RDWR | O_NOCTTY);
if(cdcFile == -1){
std::cerr << "Failed to open CDC device file" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
@ -23,13 +32,18 @@ void Receiver::openStream(){
}
}
void Receiver::closeStream(){
close(cdcFile);
}
int Receiver::initSerial(){
memset(&tty, 0, sizeof(tty));
if (tcgetattr(cdcFile, &tty) != 0) {
std::cerr << "Error in tcgetattr" << std::endl;
return -1;
}
//tcflush(cdcFile, TCIFLUSH);
//CDC communication configuration
cfsetospeed(&tty, B115200);
cfsetispeed(&tty, B115200);
tty.c_cflag |= (CLOCAL | CREAD);
@ -119,49 +133,25 @@ int Receiver::simulateRead(unsigned char (*character)[CDC_FRAME_SIZE]){
}
int Receiver::getDistance(){
uint16_t dist = 0;
int distCorrupted = 1;
unsigned char distanceFrame[12];
int bytesRead = read(cdcFile, distanceFrame, 12);
if(bytesRead == -1){
std::cout<<"ERROR IN READ!!! ";
}
std::cout<<"distance: ";
for(int i=0; i<7; i++){
if(distanceFrame[i] == 0xff && distanceFrame[i+1] == 0x69 && distanceFrame [i+4] == 0xff && distanceFrame[i+5] == 0x69){
dist = (distanceFrame[i+2] << 8 | distanceFrame[i+3]);
std::cout << " - " << static_cast<int>(dist) << " - ";
Receiver::printHex(distanceFrame[i+2]);
std::cout << " ";
Receiver::printHex(distanceFrame[i+3]);
std::cout << std::endl;
distCorrupted = 0;
return 0;
distance = (distanceFrame[i+2] << 8 | distanceFrame[i+3]);
}
}
if(distCorrupted) {
std::cout << "Corrupted :( -> ";
for(int i = 0; i<12; i++) {
Receiver::printHex(distanceFrame[i]);
std::cout << " ";
}
std::cout << std::endl;
}
std::cout << " Distance: " << std::dec << distance << " mm" << std::endl;
return 1;
}
int Receiver::fillBuffer(){
int Receiver::fillBuffer(bool saveToFile){
unsigned char character[CDC_FRAME_SIZE];
std::vector<uint8_t> tempVec{};
@ -187,18 +177,16 @@ int Receiver::fillBuffer(){
Receiver::getDistance();
//////////// SAVE FRAMES TO FILES
/*
std::ofstream outfile(std::to_string(debugFileIdx) + ".jpg", std::ios::out | std::ios::binary);
if (!outfile.is_open()) {
std::cerr << "Failed to create file " << debugFileIdx << ".jpg" << std::endl;
return 1;
if(saveToFile){
std::ofstream outfile(std::to_string(debugFileIdx) + "_" + std::to_string(distance) + "_mm" + ".jpg", std::ios::out | std::ios::binary);
if (!outfile.is_open()) {
std::cerr << "Failed to create file " << debugFileIdx << ".jpg" << std::endl;
return 1;
}
outfile.write(reinterpret_cast<const char*>(tempVec.data()), tempVec.size());
outfile.close();
debugFileIdx++;
}
outfile.write(reinterpret_cast<const char*>(tempVec.data()), tempVec.size());
outfile.close();
debugFileIdx++;
*/
////////////
currentBufferIndexMutex.lock();
@ -223,22 +211,19 @@ int Receiver::fillBuffer(){
return 1;
}
void Receiver::bufferToDisplay(){
void Receiver::bufferToDisplay(bool printRaw){
currentBufferIndexMutex.lock();
int buffIdx = currentBufferIndex;
currentBufferIndexMutex.unlock();
switch(buffIdx){
case 0:
//std::cout << buffer1.size() << std::endl;
dis->vectorToTexture(&buffer1);
dis->vectorToTexture(&buffer1, printRaw);
break;
case 1:
//std::cout << buffer2.size() << std::endl;
dis->vectorToTexture(&buffer2);
dis->vectorToTexture(&buffer2, printRaw);
break;
case 2:
//std::cout << buffer3.size() << std::endl;
dis->vectorToTexture(&buffer3);
dis->vectorToTexture(&buffer3, printRaw);
break;
default:
std::cout << "error 86" << std::endl;

@ -1,9 +1,23 @@
/**
* @file Receiver.hpp
* @brief Header file for the Receiver class.
* @author Adam Prochazka <xproch0f>
*
* This file contains the declaration of the Receiver class which is responsible for
* managing the serial communication and processing the received data to display images.
*/
#include "main.hpp"
#ifndef DISPLAYER_HPP
#include "Displayer.hpp"
#endif
/**
* @class Receiver
* @brief Handles receiving data from the serial port and buffering the data for the Displayer.
*/
class Receiver{
private:
int cdcFile;
@ -49,27 +63,99 @@ class Receiver{
std::vector<uint8_t> buffer3;
Displayer *dis;
int sequenceEndedFF = 0;
int distance = 0;
int sequenceEndedFF = 0; ///< Flag to indicate if the sequence has ended with 0xFF.
int simulateIdx = 0;
int debugFileIdx = 0;
public:
/**
* @brief Constructor for the Receiver class.
* @param displayerPtr Pointer to the Displayer instance.
*/
Receiver(Displayer *displayerPtr);
void openStream();
/**
* @brief Opens the serial port stream.
* @param port Name of serial port to be openned.
*/
void openStream(char * port);
/**
* @brief Closes the serial port stream.
*/
void closeStream();
/**
* @brief Initializes the serial port settings.
* @return 1 if successful, -1 if an error occurred.
*/
int initSerial();
/**
* @brief Reads data from the CDC device.
* @param[out] character Pointer to the character buffer to store the read data.
* @return 0 if successful, -1 if error occurred.
*/
int readCdcData(unsigned char (*character)[CDC_FRAME_SIZE]);
/**
* @brief Prints char as hexadecimal value with a 0x prefix.
* @param value The char to be printed.
*/
void printHex(unsigned char value);
int fillBuffer();
/**
* @brief Fills the buffer with data from the serial port.
* @param saveToFile Indicates if image data should be saved to file.
* @return 0.
*/
int fillBuffer(bool saveToFile = false);
/**
* @brief Gets the distance data from serial port and print it to std out.
* @return 0 if successful, 1 if error occurred.
*/
int getDistance();
void bufferToDisplay();
/**
* @brief Sends the buffer to the Displayer for rendering.
* @param printRaw Bool that indicates weather received byte data should be printed to std::out (for debug).
*/
void bufferToDisplay(bool printRaw = false);
/**
* @brief Initializes textures in Displayer to default values.
*/
void initTextures();
/**
* @brief Finds a sequence of two characters in the given string.
* @param[in] str Pointer to the input string.
* @param ch1 First character of the sequence to find.
* @param ch2 Second character of the sequence to find.
* @return Index of the first occurrence of the sequence, or -1 if not found.
*/
int findSequence(unsigned char (*str)[CDC_FRAME_SIZE], unsigned char ch1, unsigned char ch2);
/**
* @brief Find index of bytes signalizing start of image.
* @param[in] str Pointer to the input string.
* @return Index of the start of the data sequence, or -1 if not found.
*/
int findStart(unsigned char (*str)[CDC_FRAME_SIZE]);
/**
* @brief Find index of bytes signalizing end of image.
* @param[in] str Pointer to the input string.
* @return Index of the start of the data sequence, or -1 if not found.
*/
int findEnd(unsigned char (*str)[CDC_FRAME_SIZE]);
/**
* @brief Test function to simulate reading from serial port.
* @param[in] str Pointer to the string buffer.
* @return 0.
*/
int simulateRead(unsigned char (*character)[CDC_FRAME_SIZE]);
};

@ -1,3 +1,12 @@
/**
* @file main.cpp
* @brief Source file for the main application.
* @author Adam Prochazka <xproch0f>
*
* This file contains the implementation of the main application, which integrates the Receiver
* and Displayer classes, manages their threads, and handles the overall execution flow.
*/
#include "main.hpp"
#include "Receiver.hpp"
@ -5,13 +14,18 @@
#include "Displayer.hpp"
#endif
int cdcFile;
void readLoop(Receiver ** receiverPtr){
(*receiverPtr)->openStream();
int cdcFile;
bool quit = false;
/**
* @brief Reads and processes data from the serial communication in a loop. - for debug purposes
* @param receiverPtr Pointer to a pointer to the Receiver class instance.
* @param port Serial port to be opened.
*/
void readLoop(Receiver ** receiverPtr, char * port){
(*receiverPtr)->openStream(port);
(*receiverPtr)->initSerial();
while (true) {
while (!quit) {
unsigned char character[CDC_FRAME_SIZE];
(*receiverPtr)->readCdcData(&character);
if((*receiverPtr)->findStart(&character) != -1)
@ -27,28 +41,74 @@ void readLoop(Receiver ** receiverPtr){
close(cdcFile);
}
/**
* @brief Flips through the textures in a separate thread.
* @param displayerPtr Pointer to the Displayer class instance.
*/
void windowFlipThread(Displayer * displayerPtr){
displayerPtr->flipThroughTextures();
}
/**
* @brief Wrapper function to call bufferToDisplay() method of the Receiver instance.
* @param receiverPtr Pointer to a pointer to the Receiver instance.
*/
void WrapperBufferToDisplay(Receiver ** receiverPtr){
(*receiverPtr)->bufferToDisplay();
}
void receiverLoop(Receiver ** receiverPtr){
/**
* @brief Main loop for the Receiver instance.
* @param receiverPtr Pointer to a pointer to the Receiver instance.
*/
void receiverLoop(Receiver ** receiverPtr, bool *q, bool printRaw, bool saveToFile){
std::vector<std::thread> displayThreads;
while(1){
while(!(*q)){
(*receiverPtr)->fillBuffer(saveToFile);
(*receiverPtr)->bufferToDisplay(printRaw);
(*receiverPtr)->fillBuffer();
std::thread t2(WrapperBufferToDisplay, receiverPtr);
t2.detach();
//running in a thread also works, but for simplicity is not used.
//std::thread t2(WrapperBufferToDisplay, receiverPtr);
//t2.detach();
}
}
int main()
int main(int argc, char * argv[])
{
char * port = nullptr;
bool printRaw = false;
bool saveToFile = false;
int opt;
while ((opt = getopt(argc, argv, "p:r:s")) != -1) {
switch (opt) {
case 'p':
port = optarg;
break;
case 'r':
printRaw = true;
break;
case 's':
saveToFile = true;
break;
default:
std::cerr << "Usage: sudo ./main -p <serial_port> [-r to print raw data] [-s to save images]" << std::endl;
std::cerr << "Example: sudo ./main -p /dev/ttyACM0 -r -s" << std::endl;
return 1;
}
}
if (!port) {
std::cerr << "Serial port not specified" << std::endl;
return 1;
}
std::cout << "Serial port: " << port << std::endl;
std::cout << "Print raw data: " << (printRaw ? "true" : "false") << std::endl;
std::cout << "Save images: " << (saveToFile ? "true" : "false") << std::endl;
Displayer dis;
Receiver *rec = new Receiver(&dis);
@ -56,7 +116,7 @@ int main()
dis.createWindow();
dis.renderWindow();
rec->openStream();
rec->openStream(port);
rec->initSerial();
rec->initTextures();
@ -64,13 +124,12 @@ int main()
rec->fillBuffer();
rec->bufferToDisplay();
std::thread t1(receiverLoop, &rec);
dis.windowLoop();
std::thread t1(receiverLoop, &rec, &quit, std::ref(printRaw), std::ref(saveToFile));
t1.detach();
t1.join();
dis.windowLoop(&quit);
rec->closeStream();
readLoop(&rec);
return 0;
}

@ -1,3 +1,11 @@
/**
* @file main.hpp
* @brief Header file for the main application.
* @author Adam Prochazka <xproch0f>
*
* This file contains the includes, definitions, and declarations required for the main application.
*/
#include <iostream>
#include <cstring>
#include <cstdint>

File diff suppressed because it is too large Load Diff

@ -1,16 +0,0 @@
CC = gcc
CFLAGS = -Wall -Wextra
SRCS = uart_jpeg.c
OBJS = $(SRCS:.c=.o)
all: uart_jpeg
uart_jpeg: $(OBJS)
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c $<
clean:
rm -f $(OBJS) uart_jpeg

@ -1,121 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
int main()
{
int fd;
unsigned char buffer[100000];
unsigned char tempBuff[1];
// Open the UART device
fd = open("/dev/ttyACM0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("Error opening UART device");
return -1;
}
// Configure the UART settings
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &options);
// Read a single byte from the UART device
int fileCount = 1;
while (1)
{
if (read(fd, tempBuff, 1) != 1)
{
continue;
}
if (tempBuff[0] != (unsigned char)255)
{
continue;
}
if (read(fd, tempBuff, 1) != 1)
{
continue;
}
if (tempBuff[0] != (unsigned char)216)
{
continue;
}
unsigned int currentIndex = 2;
buffer[0] = 255;
buffer[1] = 216;
while (1)
{
if (read(fd, tempBuff, 1) != 1)
{
continue;
}
buffer[currentIndex++] = tempBuff[0];
if (tempBuff[0] != 0xFF)
{
continue;
}
if (read(fd, tempBuff, 1) != 1)
{
continue;
}
buffer[currentIndex++] = tempBuff[0];
if (tempBuff[0] == 0xD8)
{
printf("Corrupted File, start over...\n");
memset(buffer, 0x00, sizeof(buffer));
currentIndex = 2;
buffer[0] = 0xFF;
buffer[1] = 0xD8;
continue;
}
if (tempBuff[0] == 0xD9)
{
// END FOUND
char fileName[11] = {'0', '0', '0', '0', '0', '.', 'j', 'p', 'e', 'g', '\0'};
char secondDigit = (fileCount % 10) + '0';
char firstDigit = (fileCount / 10) + '0';
fileName[0] = firstDigit;
fileName[1] = secondDigit;
FILE *fp = fopen(fileName, "wb");
if (fp == NULL)
{
printf("Error opening file!\n");
return 1;
}
for (unsigned int i = 0; i < currentIndex; i++)
{
unsigned char myChar = buffer[i];
fwrite(&myChar, sizeof(unsigned char), 1, fp);
}
// Close the file
fclose(fp);
printf("File %s saved!\n", fileName);
memset(buffer, 0x00, sizeof(buffer));
fileCount++;
break;
}
}
}
// Close the UART device
close(fd);
return 0;
}
Loading…
Cancel
Save