/**
 ******************************************************************************
 * File Name          : main.c
 * Description        : Main program body
 ******************************************************************************
 *
 * COPYRIGHT(c) 2015 STMicroelectronics
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of STMicroelectronics nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/

#include <stdio.h>	/*rtt*/
#include <stdlib.h>	/*rtt*/
#include "stm32f4xx_hal.h"
#include "stm32f4_discovery.h"
#include "cmsis_os.h"
#include "adc.h"
#include "can.h"
#include "crc.h"
#include "i2c.h"
#include "i2s.h"
#include "rng.h"
#include "spi.h"
#include "tim.h"
#include "usart.h"
#include "usb_device.h"
#include "gpio.h"

/* USER CODE BEGIN Includes */
#include "usbd_cdc_if.h"

/* USER CODE END Includes */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
/* LED Private Variables */
osThreadId LEDThread1Handle, LEDThread2Handle, LEDThread3Handle,
		LEDThread4Handle;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);
void MX_FREERTOS_Init(void);

/* USER CODE BEGIN PFP */
extern void initialise_monitor_handles(void);	/*rtt*/
/*LED Function Prototypes */
static void LED_Thread1(void const *argument);
static void LED_Thread2(void const *argument);
static void LED_Thread3(void const *argument);
static void LED_Thread4(void const *argument);

/* USER CODE END PFP */

/* USER CODE BEGIN 0 */


/* USER CODE END 0 */

int main(void) {

	/* USER CODE BEGIN 1 */
	initialise_monitor_handles();	/*rtt*/

	puts("Standard output message.");	/*rtt*/
	puts("Gotta love this shit.");		/*rtt*/
	printf("The String\n");

	/* USER CODE END 1 */

	/* MCU Configuration----------------------------------------------------------*/

	/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
	HAL_Init();

	/* Configure the system clock */
	SystemClock_Config();

	/* Initialize all configured peripherals */
	MX_GPIO_Init();
	MX_ADC1_Init();
	MX_ADC2_Init();
	MX_ADC3_Init();
	MX_CAN1_Init();
	MX_CAN2_Init();
	MX_CRC_Init();
	MX_I2C1_Init();
	MX_I2C3_Init();
	MX_I2S3_Init();
	MX_RNG_Init();
	MX_SPI1_Init();
	MX_TIM6_Init();
	MX_TIM7_Init();
	MX_USART3_UART_Init();

	/* USER CODE BEGIN 2 */
	/* Configure all four LEDs*/
	BSP_LED_Init(LED3);
	BSP_LED_Init(LED4);
	BSP_LED_Init(LED5);
	BSP_LED_Init(LED6);

	/**
	 ******************************************************************************
	 * Description        : Thread definition for the LED flashing
	 ******************************************************************************
	 **/
	/* Thread 1 definition and assign to LED */
	osThreadDef(LED3, LED_Thread1, osPriorityNormal, 0,
			configMINIMAL_STACK_SIZE);

	/* Thread 2 definition and assign to LED */
	osThreadDef(LED4, LED_Thread2, osPriorityNormal, 0,
			configMINIMAL_STACK_SIZE);

	/* Thread 3 definition and assign to LED */
	osThreadDef(LED5, LED_Thread3, osPriorityNormal, 0,
			configMINIMAL_STACK_SIZE);

	/* Thread 4 definition and assign to LED */
	osThreadDef(LED6, LED_Thread4, osPriorityNormal, 0,
			configMINIMAL_STACK_SIZE);

	/**
	 ******************************************************************************
	 * Description        : Thread creation to flash the LEDs
	 ******************************************************************************
	 **/
	/* Start Thread 1 */
	LEDThread1Handle = osThreadCreate(osThread(LED3), NULL);

	/* Start Thread 2 */
	LEDThread2Handle = osThreadCreate(osThread(LED4), NULL);

	/* Start Thread 3 */
	LEDThread3Handle = osThreadCreate(osThread(LED5), NULL);

	/* Start Thread 4 */
	LEDThread4Handle = osThreadCreate(osThread(LED6), NULL);

	/* USER CODE END 2 */

	/* Call init function for freertos objects (in freertos.c) */


	MX_FREERTOS_Init();

	/* Start scheduler */
	osKernelStart();

	/* We should never get here as control is now taken by the scheduler */

	/* Infinite loop */
	/* USER CODE BEGIN WHILE */

	while (1) {
		/* USER CODE END WHILE */

		/* USER CODE BEGIN 3 */


	}
	/* USER CODE END 3 */

}

/* Toggle LED3 */
static void LED_Thread1(void const *argument) {
	uint32_t count = 0;
	(void) argument;

	for (;;) {
		count = osKernelSysTick() + 50;

		/* Toggle LED3 every 200 ms */
		while (count >= osKernelSysTick()) {
			BSP_LED_Toggle(LED3);

			osDelay(200);
		}
	}
	BSP_LED_Off(LED3);
}

/* Toggle LED4 */
static void LED_Thread2(void const *argument) {
	uint32_t count;
	(void) argument;

	for (;;) {
		count = osKernelSysTick() + 50000;

		/* Toggle LED4 every 400 ms */
		while (count >= osKernelSysTick()) {
			BSP_LED_Toggle(LED4);

			osDelay(400);
		}

	}
}

/* Toggle LED5 */
static void LED_Thread3(void const *argument) {
	uint32_t count;
	(void) argument;

	for (;;) {
		count = osKernelSysTick() + 50;

		/* Toggle LED5 every 500 ms */
		while (count >= osKernelSysTick()) {
			BSP_LED_Toggle(LED5);

			osDelay(500);
		}

	}
}

/* Toggle LED6 */
static void LED_Thread4(void const *argument) {
	uint32_t count;
	(void) argument;

	for (;;) {
		count = osKernelSysTick() + 50000;

		/* Toggle LED5 every 600 ms */
		while (count >= osKernelSysTick()) {
			BSP_LED_Toggle(LED6);

			osDelay(600);
		}

	}
}

/** System Clock Configuration
 */
void SystemClock_Config(void) {

	RCC_OscInitTypeDef RCC_OscInitStruct;
	RCC_ClkInitTypeDef RCC_ClkInitStruct;
	RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;

	__PWR_CLK_ENABLE()
	;

	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
	RCC_OscInitStruct.HSEState = RCC_HSE_ON;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
	RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
	RCC_OscInitStruct.PLL.PLLM = 8;
	RCC_OscInitStruct.PLL.PLLN = 336;
	RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
	RCC_OscInitStruct.PLL.PLLQ = 7;
	HAL_RCC_OscConfig(&RCC_OscInitStruct);

	RCC_ClkInitStruct.ClockType = 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_DIV4;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
	HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5);

	PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
	PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
	PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
	HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

	HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);

	HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

#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

/**
 * @}
 */

/**
 * @}
 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
