<commit_before>#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#include "arm_math.h"
#include "arm_const_structs.h"
#include "cmsis_os.h"

#include "app.h"
#include "drivers/led.h"
#include "main.h"

// No idea why this isn't included in any headers from ST...
#if defined(STM32L432xx)
#define VREFINT_CAL	((volatile uint16_t*)0x1FFF75AAU)
#elif defined(STM32L052xx)
#define VREFINT_CAL	((volatile uint16_t*)0x1FF80078U)
#endif

#define NOTIFY_ADC_COMPLETE			0x01

extern QueueHandle_t TouchDataQHandle;
extern QueueHandle_t LedCmdQHandle;

static TaskHandle_t adc_task_handle = NULL;

static const struct led_color green = {
	.red = 0,
	.green = 128,
	.blue = 0
};

static inline void thermistor_enable(void)
{
	HAL_GPIO_WritePin(THERM_SW_GPIO_Port, THERM_SW_Pin, GPIO_PIN_SET);
	// The thermistor has a long rise time due to the cable.
	osDelay(20);
}

static inline void thermistor_disable(void)
{
	HAL_GPIO_WritePin(THERM_SW_GPIO_Port, THERM_SW_Pin, GPIO_PIN_RESET);
}

static void adc_select_channel(uint32_t channel)
{
	ADC_ChannelConfTypeDef adc_channel_config;
	adc_channel_config.Channel = channel;
	adc_channel_config.Rank = ADC_RANK_CHANNEL_NUMBER;

	// TODO: Check for and disable Vrefint if needed.
	ADC_DEV.Instance->CHSELR &= ~ADC_CHANNEL_MASK;
	if (HAL_ADC_ConfigChannel(&ADC_DEV, &adc_channel_config) != HAL_OK)
	{
		Error_Handler();
	}
}

static void adc_perform_conversion(void)
{
	if (HAL_ADC_Start_IT(&ADC_DEV) != HAL_OK)
	{
		Error_Handler();
	}

	uint32_t task_notify_val;
	if (xTaskNotifyWait(0, NOTIFY_ADC_COMPLETE, &task_notify_val, 90))
	{
		if (! (task_notify_val & NOTIFY_ADC_COMPLETE))
		{
			Error_Handler();
		}
	}
	else
	{
		// Timeout
		Error_Handler();
	}

	(void)HAL_ADC_Stop_IT(&ADC_DEV);
}

static uint16_t read_touch_sense(void)
{
	uint16_t tsc_value;

	HAL_TSC_IODischarge(&TSC_DEV, ENABLE);
	osDelay(1);

	if (HAL_TSC_Start_IT(&TSC_DEV) != HAL_OK)
	{
		Error_Handler();
	}

	if (! xQueueReceive(TouchDataQHandle, &tsc_value, 50))
	{
		Error_Handler();
	}

	(void)HAL_TSC_Stop_IT(&TSC_DEV);

	return tsc_value;
}

static float compute_thermistor_temp_C(uint16_t adc_counts)
{
	float counts_f = adc_counts;
	float temperature_C =  THERMISTOR_X3*(counts_f*counts_f*counts_f) +
						   THERMISTOR_X2*(counts_f*counts_f) +
						   THERMISTOR_X1*(counts_f) +
						   THERMISTOR_X0;
	return temperature_C;
}

static void compute_led_color(uint32_t temp_C, struct led_color *output)
{
	if (!output)
	{
		return;
	}

	memset(output, 0, sizeof(*output));

	if (temp_C >= 60)
	{
		output->red = 255;
	}
	else if (temp_C > 26)
	{
		// Linear fit 26..60C to 0..8, then convert log scale with 2**x.
		// y = (8-0)/(60-26)*(x-26)
		output->red = 1<<(((4*(temp_C-26)))/17);
	}
	else if (temp_C > 10)
	{
		// Linear 10..26C to 8..0, then convert to log scale.
		// y = (0-8)/(26-10)*(x-26) => y = (26-x)/2
		output->blue = 1<<(((26-temp_C))/2);
	}
	else
	{
		output->blue = 255;
	}
}

SleepType_E app_get_sleep_capability(void)
{
	uint32_t adc_state = HAL_ADC_GetState(&ADC_DEV);
	if ((adc_state & HAL_ADC_STATE_REG_BUSY) ||
		(HAL_TSC_GroupGetStatus(&TSC_DEV, TOUCH_SENSE_GROUP) != TSC_GROUP_COMPLETED) ||
		led_get_active())<commit_msg>Make cold <= 26C, hot >= 27C.<commit_after>#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>

#include "arm_math.h"
#include "arm_const_structs.h"
#include "cmsis_os.h"

#include "app.h"
#include "drivers/led.h"
#include "main.h"

// No idea why this isn't included in any headers from ST...
#if defined(STM32L432xx)
#define VREFINT_CAL	((volatile uint16_t*)0x1FFF75AAU)
#elif defined(STM32L052xx)
#define VREFINT_CAL	((volatile uint16_t*)0x1FF80078U)
#endif

#define NOTIFY_ADC_COMPLETE			0x01

extern QueueHandle_t TouchDataQHandle;
extern QueueHandle_t LedCmdQHandle;

static TaskHandle_t adc_task_handle = NULL;

static const struct led_color green = {
	.red = 0,
	.green = 128,
	.blue = 0
};

static inline void thermistor_enable(void)
{
	HAL_GPIO_WritePin(THERM_SW_GPIO_Port, THERM_SW_Pin, GPIO_PIN_SET);
	// The thermistor has a long rise time due to the cable.
	osDelay(20);
}

static inline void thermistor_disable(void)
{
	HAL_GPIO_WritePin(THERM_SW_GPIO_Port, THERM_SW_Pin, GPIO_PIN_RESET);
}

static void adc_select_channel(uint32_t channel)
{
	ADC_ChannelConfTypeDef adc_channel_config;
	adc_channel_config.Channel = channel;
	adc_channel_config.Rank = ADC_RANK_CHANNEL_NUMBER;

	// TODO: Check for and disable Vrefint if needed.
	ADC_DEV.Instance->CHSELR &= ~ADC_CHANNEL_MASK;
	if (HAL_ADC_ConfigChannel(&ADC_DEV, &adc_channel_config) != HAL_OK)
	{
		Error_Handler();
	}
}

static void adc_perform_conversion(void)
{
	if (HAL_ADC_Start_IT(&ADC_DEV) != HAL_OK)
	{
		Error_Handler();
	}

	uint32_t task_notify_val;
	if (xTaskNotifyWait(0, NOTIFY_ADC_COMPLETE, &task_notify_val, 90))
	{
		if (! (task_notify_val & NOTIFY_ADC_COMPLETE))
		{
			Error_Handler();
		}
	}
	else
	{
		// Timeout
		Error_Handler();
	}

	(void)HAL_ADC_Stop_IT(&ADC_DEV);
}

static uint16_t read_touch_sense(void)
{
	uint16_t tsc_value;

	HAL_TSC_IODischarge(&TSC_DEV, ENABLE);
	osDelay(1);

	if (HAL_TSC_Start_IT(&TSC_DEV) != HAL_OK)
	{
		Error_Handler();
	}

	if (! xQueueReceive(TouchDataQHandle, &tsc_value, 50))
	{
		Error_Handler();
	}

	(void)HAL_TSC_Stop_IT(&TSC_DEV);

	return tsc_value;
}

static float compute_thermistor_temp_C(uint16_t adc_counts)
{
	float counts_f = adc_counts;
	float temperature_C =  THERMISTOR_X3*(counts_f*counts_f*counts_f) +
						   THERMISTOR_X2*(counts_f*counts_f) +
						   THERMISTOR_X1*(counts_f) +
						   THERMISTOR_X0;
	return temperature_C;
}

static void compute_led_color(uint32_t temp_C, struct led_color *output)
{
	if (!output)
	{
		return;
	}

	memset(output, 0, sizeof(*output));

	if (temp_C >= 60)
	{
		output->red = 255;
	}
	else if (temp_C >= 28)
	{
		// Linear fit 28..60C to 0..8, then convert log scale with 2**x.
		// y = (8-0)/(60-28)*(x-28) => y = (x-28)/4
		output->red = 1<<((1*(temp_C-28))/4);
	}
	else if (temp_C >= 10)
	{
		// Linear 10..27C to 8..0, then convert to log scale.
		// y = (0-8)/(27-10)*(x-26) => y = 8*(27-x)/17
		output->blue = 1<<(8*(27-temp_C)/17);
	}
	else
	{
		output->blue = 255;
	}
}

SleepType_E app_get_sleep_capability(void)
{
	uint32_t adc_state = HAL_ADC_GetState(&ADC_DEV);
	if ((adc_state & HAL_ADC_STATE_REG_BUSY) ||
		(HAL_TSC_GroupGetStatus(&TSC_DEV, TOUCH_SENSE_GROUP) != TSC_GROUP_COMPLETED) ||
		led_get_active())
{'fraction_non_alphanumeric': 0.13402380584325244, 'fraction_numerical': 0.036790848662853606, 'mean_word_length': 4.746003552397869, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1260356', 'n_tokens_mistral': 3034, 'n_tokens_neox': 2750, 'n_words': 503}