/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2022 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.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "dma.h"
#include "fatfs.h"
#include "i2c.h"
#include "libjpeg.h"
#include "sdio.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "usb_host.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
#include "TFT_ILI9341.h"
#include "GFX_Color.h"
#include "GFX_EnhancedFonts.h"
#include "EnhancedFonts/arialBlack_20ptFontInfo.h"
#include "NRF905.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define LED_NUM 8
#define ADDRESS_MASTER 0x25D34478
#define ADDRESS_SLAVE  0x6DA0C59B

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
extern ApplicationTypeDef Appli_state;

extern uint8_t retSD; /* Return value for SD */
extern char SDPath[4]; /* SD logical drive path */
extern FATFS SDFatFS; /* File system object for SD logical drive */
extern FIL SDFile; /* File object for SD */

extern uint8_t retUSBH; /* Return value for USBH */
uint8_t retUSBHprevious = 254; /* Return value for USBH */
extern char USBHPath[4]; /* USBH logical drive path */
extern FATFS USBHFatFS; /* File system object for USBH logical drive */
extern FIL USBHFile; /* File object for USBH */

TCHAR *original_file_name[256];
TCHAR *copied_file_name[256];

DIR dirobj; /* Directory object */
FILINFO finfo; /* File information */

uint32_t SlideshowTimer;
uint8_t FirstSlide = 0;

uint8_t bytes;
char data[256];

uint8_t LED_Data[LED_NUM][4];
uint16_t pwmData[50 + (24 * LED_NUM)];

volatile int datasentflag = 0;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_USB_HOST_Process(void);

/* USER CODE BEGIN PFP */
uint8_t Copy_FATFS_File_ver1(const TCHAR *original_file_name,
		const TCHAR *copied_file_name);
uint8_t Copy_FATFS_File_ver2(const TCHAR *original_file_name,
		const TCHAR *copied_file_name);
void Print_SD_Result(uint8_t ret);
void Message_from_USB_Translator(uint8_t retUSBH, uint8_t bytes, char data[256]);
void Set_LED(uint8_t LEDnum, uint8_t Red, uint8_t Green, uint8_t Blue);
void WS2812B_Send(void);
void Reset_LED(void);
void SetLED0Blue(void);
void SetLED4Blue(void);
void SetLED0Green(void);
void SetLED4Green(void);
void SetLED0Yellow(void);
void SetLED0Red(void);
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim);

int _write(int file, char *ptr, int len)
{
	HAL_UART_Transmit(&huart2, (uint8_t*) ptr, len, 50);
	for (int i = 0; i < len; i++)
	{
		ITM_SendChar(*ptr++);
	}
	return len;
}
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
NRF905_hw_t NRF905_hw;
NRF905_t NRF905;

int master = 1;
int ret;

char buffer[64];
char nrf905_payload_buffer[NRF905_MAX_PAYLOAD + 1];
char nrf905_payload_print[128];

typedef struct
{
	char file_name[20];
	char message[10];
} payload32_t;

payload32_t nrf905_payload_structured;

int message;
int message_length;

uint32_t my_address;
uint32_t receiver_address;
/* USER CODE END 0 */

/**
 * @brief  The application entry point.
 * @retval int
 */
int main(void)
{
	/* USER CODE BEGIN 1 */

	/* USER CODE END 1 */

	/* MCU Configuration--------------------------------------------------------*/

	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();

	/* USER CODE BEGIN Init */

	/* USER CODE END Init */

	/* Configure the system clock */
	SystemClock_Config();

	/* USER CODE BEGIN SysInit */

	/* USER CODE END SysInit */

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_USART2_UART_Init();
	MX_DMA_Init();
	MX_SDIO_SD_Init();
	MX_FATFS_Init();
	MX_USB_HOST_Init();
	MX_TIM3_Init();
	MX_SPI2_Init();
	MX_I2C1_Init();
	MX_I2C2_Init();
	MX_I2C3_Init();
	MX_SPI3_Init();
	MX_LIBJPEG_Init();
	MX_TIM9_Init();
	/* USER CODE BEGIN 2 */

	ILI9341_Init(&hspi2);
	EF_SetFont(&arialBlack_20ptFontInfo);

	ILI9341_ClearDisplay(ILI9341_BLUE);

	HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
	retSD = f_mount(&SDFatFS, SDPath, 1);
	Print_SD_Result(retSD);
	SlideshowTimer = HAL_GetTick();

	uint32_t uid = 0x00;
	for (uint8_t i = 0; i < 3; ++i)
	{
		uid += *(uint32_t*) (UID_BASE + i * 4);
	}
	srand(uid);

	NRF905_hw.gpio[NRF905_HW_GPIO_TXEN].pin = TXEN_Pin;
	NRF905_hw.gpio[NRF905_HW_GPIO_TXEN].port = TXEN_GPIO_Port;
	NRF905_hw.gpio[NRF905_HW_GPIO_TRX_EN].pin = TRX_CE_Pin;
	NRF905_hw.gpio[NRF905_HW_GPIO_TRX_EN].port = TRX_CE_GPIO_Port;
	NRF905_hw.gpio[NRF905_HW_GPIO_PWR].pin = PWR_Pin;
	NRF905_hw.gpio[NRF905_HW_GPIO_PWR].port = PWR_GPIO_Port;

	NRF905_hw.gpio[NRF905_HW_GPIO_CD].pin = CD_Pin;
	NRF905_hw.gpio[NRF905_HW_GPIO_CD].port = CD_GPIO_Port;
	NRF905_hw.gpio[NRF905_HW_GPIO_AM].pin = 0;
	NRF905_hw.gpio[NRF905_HW_GPIO_AM].port = NULL;
	NRF905_hw.gpio[NRF905_HW_GPIO_DR].pin = 0;
	NRF905_hw.gpio[NRF905_HW_GPIO_DR].port = NULL;

	NRF905_hw.gpio[NRF905_HW_GPIO_CS].pin = SPI_CS_Pin;
	NRF905_hw.gpio[NRF905_HW_GPIO_CS].port = SPI_CS_GPIO_Port;

	NRF905_hw.tim = &htim9;
	NRF905_hw.spi = &hspi3;

	//master = HAL_GPIO_ReadPin(MODE_GPIO_Port, MODE_Pin);
	if (master == 1)
	{
		my_address = ADDRESS_MASTER;
		receiver_address = ADDRESS_SLAVE;
	}
	else
	{
		my_address = ADDRESS_SLAVE;
		receiver_address = ADDRESS_MASTER;
	}

	NRF905_init(&NRF905, &NRF905_hw);
	NRF905_set_listen_address(&NRF905, receiver_address);

	printf("Reg conf: ");
	for (int i = 0; i < 10; ++i)
	{
		uint8_t d = NRF905_read_config_register(&NRF905, i);
		printf("%02X, ", d);
	}
	printf("\r\n");
	/* USER CODE END 2 */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */
	while (1)
	{

		switch (Appli_state)
		{
		case APPLICATION_IDLE:
			SetLED0Blue();
			break;
		case APPLICATION_START:
			SetLED4Blue();
			retUSBH = f_mount(&USBHFatFS, USBHPath, 0);

			//
			// FatFS mount init error check
			//

			if (retUSBH != retUSBHprevious)
			{
				retUSBHprevious = retUSBH;
				Message_from_USB_Translator(retUSBH, bytes, data);
				HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
			}
			break;

		case APPLICATION_READY:
			SetLED0Green();
			if ((retUSBH == FR_OK) && (FirstSlide == 0))
			{
				retUSBH = f_findfirst(&dirobj, &finfo, USBHPath, "*.jpg"); /* Start to search for photo files */
				if (retUSBH == FR_OK)
				{
					FirstSlide = 1;
					SlideshowTimer = HAL_GetTick();
				}
			}
			if ((retUSBH == FR_OK) && (finfo.fname[0] != 0)
					&& ((HAL_GetTick() - SlideshowTimer) > 3000))
			{ /* Repeat while an item is found */
				SlideshowTimer = HAL_GetTick();
				SetLED4Green();
				ILI9341_ClearDisplay(ILI9341_WHITE);
				f_chdrive(USBHPath);

				ILI9341_DrawJPEG(0, 0, finfo.fname);

				//copy displayed .jpg to SD card
				strcpy((char*) original_file_name, USBHPath);
				strcat((char*) original_file_name, finfo.fname);
				strcpy((char*) copied_file_name, SDPath);
				strcat((char*) copied_file_name, finfo.fname);
				Copy_FATFS_File_ver1((char*) original_file_name,
						(char*) copied_file_name);
				EF_PutString((uint8_t*) ("Copied to SD card."), 10, 200,
						ILI9341_BLACK, BG_TRANSPARENT, ILI9341_MAGENTA);

//							//nRF BEGIN
				strncpy(nrf905_payload_structured.file_name, finfo.fname, 20);
				nrf905_payload_structured.file_name[20] = '\0';
				strcpy(nrf905_payload_structured.message, "sent");

				for (unsigned int i = 0; i < sizeof(nrf905_payload_structured);
						i++)
				{
					// +i has to be outside of the parentheses in order to increment the address
					// by the size of a char. Otherwise you would increment by the size of
					// struct_data. You also have to dereference the whole thing, or you will
					// assign an address to data[i]
					nrf905_payload_buffer[i] =
							*((char*) (&nrf905_payload_structured) + i);
				}

				sprintf(nrf905_payload_print,
						"Sending (%d): File name: = %s. Message: = %s\r\n",
						sizeof(nrf905_payload_structured),
						nrf905_payload_structured.file_name,
						nrf905_payload_structured.message);

				int ret = NRF905_tx(&NRF905, my_address, nrf905_payload_buffer,
						32, NRF905_NEXTMODE_RX);

				printf(nrf905_payload_print);
				printf("ret = %d\r\n", ret);

//							//nRF END

				retUSBH = f_findnext(&dirobj, &finfo); /* Search for next item */
			}
			if ((FirstSlide == 1) && (finfo.fname[0] == 0))
			{
				f_closedir(&dirobj);
				FirstSlide = 0;
			}

			break;

		case APPLICATION_DISCONNECT:
			SetLED0Red();
			break;

		default:
			break;
		}
		/* USER CODE END WHILE */
		MX_USB_HOST_Process();

		/* USER CODE BEGIN 3 */
	}
	/* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
	RCC_OscInitTypeDef RCC_OscInitStruct =
	{ 0 };
	RCC_ClkInitTypeDef RCC_ClkInitStruct =
	{ 0 };

	/** Configure the main internal regulator output voltage
	 */
	__HAL_RCC_PWR_CLK_ENABLE();
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	/** Initializes the RCC Oscillators according to the specified parameters
	 * in the RCC_OscInitTypeDef structure.
	 */
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState = RCC_HSE_BYPASS;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
	RCC_OscInitStruct.PLL.PLLM = 4;
	RCC_OscInitStruct.PLL.PLLN = 72;
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
	RCC_OscInitStruct.PLL.PLLQ = 3;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
	{
		Error_Handler();
	}

	/** Initializes the CPU, AHB and APB buses clocks
	 */
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
			| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
	{
		Error_Handler();
	}
}

/* USER CODE BEGIN 4 */
uint8_t Copy_FATFS_File_ver1(const TCHAR *original_file_name,
		const TCHAR *copied_file_name)
{
	uint8_t bytes;
	char data[128];
	FIL original_file, copied_file;
	FRESULT res;
	char buf[512];
	UINT br;
	UINT bw;

	res = f_open(&original_file, original_file_name, FA_READ);
	if (res != FR_OK)
	{
		bytes = sprintf(data, "Error opening source at %s .\n\r",
				original_file_name);
		HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
		return 1;
	}
	//f_close(&copied_file);
	res = f_open(&copied_file, copied_file_name, FA_WRITE | FA_CREATE_ALWAYS);
	if (res != FR_OK)
	{
		bytes = sprintf(data, "Error opening destination at %s .\n\r",
				copied_file_name);
		HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
		return 1;
	}
	do
	{
		//f_chdrive(USBHPath);
		res = f_read(&original_file, buf, sizeof(buf), &br);
		if ((res == FR_OK) && br)
		{
			//f_chdrive(SDPath);
			res = f_write(&copied_file, buf, br, &bw);
			if (res != FR_OK)
			{
				bytes = sprintf(data, "Error (%u) writing at %s .\n\r", res,
						copied_file_name);
				HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
				f_close(&original_file);
				f_close(&copied_file);
				return 1;
			}
			else
			{
				bytes = sprintf(data, "Copied: %u, %u .\n\r", br, bw);
				HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
			}
		}
	} while ((res == FR_OK) && br);
	bytes = sprintf(data, "Copied: %s to %s.\n\r", original_file_name,
			copied_file_name);
	HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
	f_close(&original_file);
	f_close(&copied_file);
	return 0;
}

uint8_t Copy_FATFS_File_ver2(const TCHAR *original_file_name,
		const TCHAR *copied_file_name)
{

	uint8_t bytes;
	char data[128];
	FIL original_file, copied_file;
	FRESULT res;
	char buffer[512];
	//char buffer[4096];
	UINT br;
	UINT bw;

	/* Open source file on the drive 1 */
	res = f_open(&original_file, original_file_name, FA_READ);
	if (res != FR_OK)
		return (uint8_t) res;

	/* Create destination file on the drive 0 */

	res = f_open(&copied_file, copied_file_name, FA_WRITE | FA_CREATE_ALWAYS);
	if (res != FR_OK)
		return (uint8_t) res;

	/* Copy source to destination */
	for (;;)
	{
		res = f_read(&original_file, buffer, sizeof(buffer), &br); /* Read a chunk of source file */
		if ((res != FR_OK) || (br == 0))
			break; /* error or eof */
		res = f_write(&copied_file, buffer, br, &bw); /* Write it to the destination file */
		if ((res != FR_OK) || (bw < br))
		{
			bytes = sprintf(data, "Write error (%u) at %s.\n\r", res,
					copied_file_name);
			HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
			break; /* error or disk full */
		}
		else
		{
			bytes = sprintf(data, "Written: %u, %u.\n\r", br, bw);
			HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
		}
	}

	bytes = sprintf(data, "Copied: %s to %s.\n\r", original_file_name,
			copied_file_name);
	HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
	/* Close open files */
	f_close(&original_file);
	f_close(&copied_file);

	return (uint8_t) res;
}

void Message_from_USB_Translator(uint8_t retUSBH, uint8_t bytes, char data[256])
{
	switch (retUSBH)
	{
	case FR_OK:
		bytes = sprintf(data, "FATFS on USB: Succeeded.\n\r");
		break;
	case FR_DISK_ERR:
		bytes =
				sprintf(data,
						"FATFS on USB: A hard error occurred in the low level disk I/O layer.\n\r");
		break;
	case FR_INT_ERR:
		bytes = sprintf(data, "FATFS on USB: Assertion failed.\n\r");
		break;
	case FR_NOT_READY:
		bytes = sprintf(data,
				"FATFS on USB: The physical drive cannot work.\n\r");
		break;
	case FR_NO_FILE:
		bytes = sprintf(data, "FATFS on USB: Could not find the file.\n\r");
		break;
	case FR_NO_PATH:
		bytes = sprintf(data, "FATFS on USB: Could not find the path.\n\r");
		break;
	case FR_INVALID_NAME:
		bytes = sprintf(data,
				"FATFS on USB: The path name format is invalid.\n\r");
		break;
	case FR_DENIED:
		bytes =
				sprintf(data,
						"FATFS on USB: Access denied due to prohibited access or directory full.\n\r");
		break;
	case FR_EXIST:
		bytes = sprintf(data,
				"FATFS on USB: Access denied due to prohibited access.\n\r");
		break;
	case FR_INVALID_OBJECT:
		bytes = sprintf(data,
				"FATFS on USB: The file/directory object is invalid.\n\r");
		break;
	case FR_WRITE_PROTECTED:
		bytes = sprintf(data,
				"FATFS on USB: The physical drive is write protected.\n\r");
		break;
	case FR_INVALID_DRIVE:
		bytes = sprintf(data,
				"FATFS on USB: The logical drive number is invalid.\n\r");
		break;
	case FR_NOT_ENABLED:
		bytes = sprintf(data, "FATFS on USB: The volume has no work area.\n\r");
		break;
	case FR_NO_FILESYSTEM:
		bytes = sprintf(data,
				"FATFS on USB: There is no valid FAT volume.\n\r");
		break;
	case FR_MKFS_ABORTED:
		bytes = sprintf(data,
				"FATFS on USB: The f_mkfs() aborted due to any problem.\n\r");
		break;
	case FR_TIMEOUT:
		bytes =
				sprintf(data,
						"FATFS on USB: Could not get a grant to access the volume within defined period.\n\r");
		break;
	case FR_LOCKED:
		bytes =
				sprintf(data,
						"FATFS on USB: The operation is rejected according to the file sharing policy.\n\r");
		break;
	case FR_NOT_ENOUGH_CORE:
		bytes = sprintf(data,
				"FATFS on USB: LFN working buffer could not be allocated.\n\r");
		break;
	case FR_TOO_MANY_OPEN_FILES:
		bytes = sprintf(data,
				"FATFS on USB: Number of open files > _FS_LOCK.\n\r");
		break;
	case FR_INVALID_PARAMETER:
		bytes = sprintf(data, "FATFS on USB: Given parameter is invalid.\n\r");
		break;
	default:
		bytes = sprintf(data, "FATFS on USB: Unknown error.\n\r");
		break;
	}
}

void Print_SD_Result(uint8_t ret)
{
	uint8_t bytes;
	char data[256];
	switch (ret)
	{
	case FR_OK:
		bytes = sprintf(data, "FATFS on SDIO: Succeeded.\n\r");
		break;
	case FR_DISK_ERR:
		bytes =
				sprintf(data,
						"FATFS on SDIO: A hard error occurred in the low level disk I/O layer.\n\r");
		break;
	case FR_INT_ERR:
		bytes = sprintf(data, "FATFS on SDIO: Assertion failed.\n\r");
		break;
	case FR_NOT_READY:
		bytes = sprintf(data,
				"FATFS on SDIO: The physical drive cannot work.\n\r");
		break;
	case FR_NO_FILE:
		bytes = sprintf(data, "FATFS on SDIO: Could not find the file.\n\r");
		break;
	case FR_NO_PATH:
		bytes = sprintf(data, "FATFS on SDIO: Could not find the path.\n\r");
		break;
	case FR_INVALID_NAME:
		bytes = sprintf(data,
				"FATFS on SDIO: The path name format is invalid.\n\r");
		break;
	case FR_DENIED:
		bytes =
				sprintf(data,
						"FATFS on SDIO: Access denied due to prohibited access or directory full.\n\r");
		break;
	case FR_EXIST:
		bytes = sprintf(data,
				"FATFS on SDIO: Access denied due to prohibited access.\n\r");
		break;
	case FR_INVALID_OBJECT:
		bytes = sprintf(data,
				"FATFS on SDIO: The file/directory object is invalid.\n\r");
		break;
	case FR_WRITE_PROTECTED:
		bytes = sprintf(data,
				"FATFS on SDIO: The physical drive is write protected.\n\r");
		break;
	case FR_INVALID_DRIVE:
		bytes = sprintf(data,
				"FATFS on SDIO: The logical drive number is invalid.\n\r");
		break;
	case FR_NOT_ENABLED:
		bytes = sprintf(data,
				"FATFS on SDIO: The volume has no work area.\n\r");
		break;
	case FR_NO_FILESYSTEM:
		bytes = sprintf(data,
				"FATFS on SDIO: There is no valid FAT volume.\n\r");
		break;
	case FR_MKFS_ABORTED:
		bytes = sprintf(data,
				"FATFS on SDIO: The f_mkfs() aborted due to any problem.\n\r");
		break;
	case FR_TIMEOUT:
		bytes =
				sprintf(data,
						"FATFS on SDIO: Could not get a grant to access the volume within defined period.\n\r");
		break;
	case FR_LOCKED:
		bytes =
				sprintf(data,
						"FATFS on SDIO: The operation is rejected according to the file sharing policy.\n\r");
		break;
	case FR_NOT_ENOUGH_CORE:
		bytes =
				sprintf(data,
						"FATFS on SDIO: LFN working buffer could not be allocated.\n\r");
		break;
	case FR_TOO_MANY_OPEN_FILES:
		bytes = sprintf(data,
				"FATFS on SDIO: Number of open files > _FS_LOCK.\n\r");
		break;
	case FR_INVALID_PARAMETER:
		bytes = sprintf(data, "FATFS on SDIO: Given parameter is invalid.\n\r");
		break;
	default:
		bytes = sprintf(data, "FATFS on SDIO: Unknown error.\n\r");
		break;
	}
	HAL_UART_Transmit(&huart2, (uint8_t*) data, bytes, 1000);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	HAL_TIM_DMABurst_WriteStop(&htim3, TIM_DMA_UPDATE);
	datasentflag = 1;
}

void Set_LED(uint8_t LEDnum, uint8_t Red, uint8_t Green, uint8_t Blue)
{
	LED_Data[LEDnum][0] = LEDnum;
	LED_Data[LEDnum][1] = Green;
	LED_Data[LEDnum][2] = Red;
	LED_Data[LEDnum][3] = Blue;
}

void WS2812B_Send(void)
{
	uint32_t indx = 0;
	uint32_t color;

	for (int i = 0; i < 50; i++)
	{
		pwmData[indx] = 0;
		indx++;
	}

	for (int i = 0; i < LED_NUM; i++)
	{
		color = ((LED_Data[i][1] << 16) | (LED_Data[i][2] << 8)
				| (LED_Data[i][3]));

		for (int i = 23; i >= 0; i--)
		{
			if (color & (1 << i))
			{
				pwmData[indx] = 75; // 3/4 of 100 //Clock at 80 MHz, counter up to 100
			}

			else
			{
				pwmData[indx] = 25; // 1/4 of 100 //Clock at 80 MHz, counter up to 100
			}
			indx++;
		}
	}

	HAL_TIM_DMABurst_MultiWriteStart(&htim3, TIM_DMABASE_CCR1, TIM_DMA_UPDATE,
			(uint32_t*) pwmData, TIM_DMABURSTLENGTH_1TRANSFER, indx);
	while (!datasentflag)
	{
	};
	datasentflag = 0;
}

void Reset_LED(void)
{
	for (int i = 0; i < LED_NUM; i++)
	{
		LED_Data[i][0] = i;
		LED_Data[i][1] = 0;
		LED_Data[i][2] = 0;
		LED_Data[i][3] = 0;
	}
}

void SetLED0Blue(void)
{
	Reset_LED();
	Set_LED(0, 0, 0, 25); //blue
	WS2812B_Send();
}

void SetLED4Blue(void)
{
	Reset_LED();
	Set_LED(4, 0, 0, 25); //blue
	WS2812B_Send();
}

void SetLED0Green(void)
{
	Reset_LED();
	Set_LED(0, 0, 25, 0); //green
	WS2812B_Send();
}

void SetLED4Green(void)
{
	Reset_LED();
	Set_LED(4, 0, 25, 0); //green
	WS2812B_Send();
}

void SetLED0Red(void)
{
	Reset_LED();
	Set_LED(0, 25, 0, 0); //red
	WS2812B_Send();
}

void SetLED0Yellow(void)
{
	Reset_LED();
	Set_LED(0, 25, 25, 0); //yellow
	WS2812B_Send();
}
/* USER CODE END 4 */

/**
 * @brief  This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
	/* USER CODE BEGIN Error_Handler_Debug */
	/* User can add his own implementation to report the HAL error return state */
	__disable_irq();
	while (1)
	{
	}
	/* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
