#include <stdio.h>
#include <stm32c0xx_hal.h> 
#include <math.h>
#include <string.h>


const float BETA = 3950.0; // Beta Coefficient of the thermistor
ADC_HandleTypeDef hadc1;
UART_HandleTypeDef huart2;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_ADC1_Init(void);
static void MX_USART2_UART_Init(void);

 
int main(void) 
{
  HAL_Init()
  SystemClock_Config();
  MX_GPIO_Init();
  MX_ADC1_Init();
  MX_USART2_UART_Init();

  char buffer[50];
  uint16_t adc_value = 0;
  float temperature = 0.0;

  while (1) 
  {
    // Start ADC conversion
    if (HAL_ADC_Start(&hadc1) != HAL_OK) 
    {
      Error_Handler();
    }

    if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) != HAL_OK) 
    {
      Error_Handler();
    }

    adc_value = HAL_ADC_GetValue(&hadc1);
    temperature = (float)adc_value * 3.3f / 4095.0f * 100.0f;
    // Print temperature value to UART
    sprintf(buffer, "Temperature: %.2f°C\r\n", temperature);
    HAL_UART_Transmit(&huart2, (uint8_t *)buffer, strlen(buffer), HAL_MAX_DELAY);
    HAL_Delay(1000); // Delay for 1 second before the next reading
  }
}


void SystemClock_Config(void) 
{
  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
   {
    Error_Handler();
  }

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
   {
    Error_Handler();
  }
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000);
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

}


static void MX_GPIO_Init(void)
 {
   GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();  // Enable GPIOA clock
    GPIO_InitStruct.Pin = GPIO_PIN_0;  // Replace with the desired ADC channel pin
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;  // Configure pin as analog
    GPIO_InitStruct.Pull = GPIO_NOPULL;  // No pull-up/pull-down
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}


static void MX_ADC1_Init(void) 
{

// Enable the ADC clock
    __HAL_RCC_ADC1_CLK_ENABLE();
    // Configure the ADC settings
    hadc.Instance = ADC1;
    hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
    hadc.Init.Resolution = ADC_RESOLUTION_12B;  // 12-bit resolution
    hadc.Init.ScanConvMode = DISABLE;           // Disable scan mode (single channel)
    hadc.Init.ContinuousConvMode = DISABLE;     // Disable continuous conversion
    hadc.Init.DiscontinuousConvMode = DISABLE;  // Disable discontinuous mode
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;  // Right-aligned data
    hadc.Init.NbrOfConversion = 1;              // Number of channels to convert
    hadc.Init.NbrOfDiscConversion = 1;          // Number of discontinuous channels
    hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;  // End of conversion selection
    if (HAL_ADC_Init(&hadc) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }
    // Configure and initialize the specific ADC channel you want to use
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_0;              // Replace with the desired channel
    sConfig.Rank = ADC_REGULAR_RANK_1;            // Rank of the channel
    sConfig.SamplingTime = ADC_SAMPLETIME_16CYCLES;  // Replace with the desired sampling time
    if (HAL_ADC_ConfigChannel(&hadc, &sConfig) != HAL_OK)
    {
        // Channel Configuration Error
        Error_Handler();
    }
}

static void MX_USART2_UART_Init(void) 
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
  __HAL_RCC_GPIOA_CLK_ENABLE();
  // PA2     ------> USART2_TX
  // PA3     ------> USART2_RX
  GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  GPIO_InitStruct.Alternate = GPIO_AF1_USART2;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
  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.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }

}


void Error_Handler(void) 
{
while (1) 
  {

  }
}

/ The following makes printf() write to USART2:

#define STDOUT_FILENO   1
#define STDERR_FILENO   2

int _write(int file, uint8_t *ptr, int len)
{
  switch (file)
  {
    case STDOUT_FILENO:
      HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
      break;

    case STDERR_FILENO:
      HAL_UART_Transmit(&huart2, ptr, len, HAL_MAX_DELAY);
      break;

    default:
      return -1;
  }

  return len;
}