////////////////////////////////////////////////////////////////////////////////
// ESERCIZIO C
////////////////////////////////////////////////////////////////////////////////
#include "stm32f030x8.h"


void display_number(int number) {
	int scaled_number = 16 - (number / 256);
	switch(scaled_number){
		case 0: /* 0 */
			GPIOB->ODR = 0b1000000;
			break;
		case 1: /* 1 */
			GPIOB->ODR = 0b1111001;
			break;
		case 2: /* 2 */
			GPIOB->ODR = 0b0100100;
			break;
		case 3: /* 3 */
			GPIOB->ODR = 0b0110000;
			break;
		case 4: /* 4 */
			GPIOB->ODR = 0b0011001;
			break;
		case 5: /* 5 */
			GPIOB->ODR = 0b0010010;
			break;
		case 6: /* 6 */
			GPIOB->ODR = 0b0000010;
			break;
		case 7: /* 7 */
			GPIOB->ODR = 0b1111000;
			break;
		case 8: /* 8 */
			GPIOB->ODR = 0b0000000;
			break;
		case 9: /* 9 */
			GPIOB->ODR = 0b0010000;
			break;
		case 10: /* A */
			GPIOB->ODR = 0b0001000;
			break;
		case 11: /* B */
			GPIOB->ODR = 0b0000011;
			break;
		case 12: /* C */
			GPIOB->ODR = 0b1000110;
			break;
		case 13: /* D */
			GPIOB->ODR = 0b0100001;
			break;
		case 14: /* E */
			GPIOB->ODR = 0b0000110;
			break;
		case 15: /* F */
			GPIOB->ODR = 0b0001110;
			break;
		default: /* - */
			GPIOB->ODR = 0b0111111;
			break;
	}

}

int cycles = 0; /* variabile che conta il numero di interrupt del conteggio */

void TIM14_IRQHandler(void) {
	if(cycles<999) { /* incremento del conteggio fino al valore 999 */
		cycles++;
	} else { /* inizializzazione del conteggio quando vale 999 (1 s) */
		cycles = 0;

		ADC1->CR |= ADC_CR_ADSTART; /* Inizio della conversione dell'ADC */
		while ((ADC1->ISR & ADC_ISR_EOC) == 0); /* Attesa di fine conversione */
		int ADC_Result = ADC1->DR; /* Salvataggio del risultato della conversione */
		display_number(ADC_Result); /* Visualizzazione del risultato sul display */

		TIM14->CCR1 = (ADC_Result*1000)/4096; /* Aggiornamento uscita PWM in base al risultato */
	}

	TIM14->SR &= 0xFFFFFFFE; /* reset del flag di interrupt pendente */
}

int main(void)
{
	int a = 0;
	int b = 1;
	int c = a+b;
	/* Configurazione della PWM */
	/* (0) Abilitazione del clock su TIM14 */
	/* (1) Configurazione del prescaler a 7 (unità di tempo 1 us) */
	/* (2) Configurazione ARR a 999, (periodo PWM 1 ms) */
	/* (3) Configurazione CCR1 iniziale a 0 (0 V sull'uscita analogica) */
	/* (4) Settaggio della PWM mode 1 su OC1 (OC1M = 110), e del preload  per OC1 (OC1PE = 1) */
	/* (5) Settaggio della polarità per OC1 (CC1P = 0, valore di reset) e abilitazione dell'output analogico su OC1 (CC1E = 1)*/
	/* (6) Abilitazione conteggio (CEN = 1), non necessaria configurazione tipologia PWM (solo edge-aligned per TIM14)  */
	/* (7) Abilitazione della maschera dell'interrupt di update */
	/* (8) Abilitazione globale del canale di interrupt di TIM14 nel NVIC*/
	/* (9) Forzatura dell'aggiornamento dei registri modificati (UG = 1) */
	RCC->APB1ENR |= RCC_APB1ENR_TIM14EN; /* (0) */
	TIM14->PSC = 7; /* (1) */
	TIM14->ARR = 999; /* (2) */
	TIM14->CCR1 = 0; /* (3) */
	TIM14->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1
		| TIM_CCMR1_OC1PE; /* (4) */
	TIM14->CCER |= TIM_CCER_CC1E; /* (5) */
	TIM14->CR1 |= TIM_CR1_CEN; /* (6) */
	TIM14->DIER |= TIM_DIER_UIE; /* (7) */
	NVIC_EnableIRQ(TIM14_IRQn); /* (8) */
	TIM14->EGR |= TIM_EGR_UG; /* (9) */

	/* Configurazione output PWM */
	/* (0) Abilitazione del clock per il GPIOA */
	/* (1) Configurazione della modalità di PA7 come output da alternate function */
	/* (2) Configurazione dell'alternate function di PA7 secondo il canale 1 di TIM14 (AFSEL7=4) */
	RCC->AHBENR |= RCC_AHBENR_GPIOAEN; /* (0) */
	GPIOA->MODER |= GPIO_MODER_MODER4_1; /* (1)*/
	GPIOA->AFR[0] |= 0x04 << GPIO_AFRL_AFRL4_Pos; /* (2) */

	/* Configurazione output display */
	/* (0) Abilitazione del clock su GPIOB */
	/* (1) Configurazione dei pin PB0:6 come output */
	/* (2) Inizializzazione dei pin per visualizzare uno zero */
	RCC->AHBENR |= RCC_AHBENR_GPIOBEN; /* (0) */
	GPIOB->MODER |= GPIO_MODER_MODER0_0 | GPIO_MODER_MODER1_0 |
			GPIO_MODER_MODER2_0 | GPIO_MODER_MODER3_0 |
			GPIO_MODER_MODER4_0 | GPIO_MODER_MODER5_0 |
			GPIO_MODER_MODER6_0; /* (1) */
	GPIOB->ODR = 0b1000000; /* (2) */

	/* Calibrazione */
	/* (0) Abilitazione del clock dell'ADC */
	/* (1) Verifica della disabilitazione dell'ADC (ADEN = 0) */
	/* (2) Se non disabilitato, disabilitazione dell'ADC (ADDIS = 1)*/
	/* (3) Inizio della calibrazione dell'ADC (ADCAL = 1) */
	/* (4) Attesa di fine calibrazione (ADCAL = 0) */
	RCC->APB2ENR |= RCC_APB2ENR_ADCEN; /* (0) */
	if ((ADC1->CR & ADC_CR_ADEN) != 0){ /* (1) */
		ADC1->CR |= ADC_CR_ADDIS; /* (2) */
	}
	while ((ADC1->CR & ADC_CR_ADEN) != 0);
	ADC1->CR |= ADC_CR_ADCAL; /* (3) */
	while ((ADC1->CR & ADC_CR_ADCAL) != 0); /* (4) */

	/* Abilitazione */
	/* (1) Verifica dello stato di !READY dell'ADC (ADRDY = 0) */
	/* (2) Se l'ADC è READY, forzatura dello stato a !READY (ADRDY = 0) */
	/* (3) Abilitazione dell'ADC (ADEN = 1) */
	/* (4) Attesa dello stato di READY dell'ADC (ADRDY = 1) */
	if ((ADC1->ISR & ADC_ISR_ADRDY) != 0){ /* (1) */
		ADC1->ISR |= ADC_ISR_ADRDY; /* (2) */
	}
	ADC1->CR |= ADC_CR_ADEN; /* (3) */
	while ((ADC1->ISR & ADC_ISR_ADRDY) == 0); /* (4) */

	/* Configurazione dell'acquisizione */
	/* (1) Selezione del clock asincrono dell'ADCCLK (CKMODE = 00) */
	/* (2) Selezione del canale di acquisizione corrispondente a PA0 (CHSEL0 = 1)  */
	/* (3) Selezione del tempo di campionamento massimo dell'ADC (SMP = 111) */
	ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* (1) */
	ADC1->CHSELR = ADC_CHSELR_CHSEL0; /* (2) */
	ADC1->SMPR |= ADC_SMPR_SMP_0|ADC_SMPR_SMP_1| ADC_SMPR_SMP_2; /* (3) */

	while(1){

	}
}

////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////