#include <cstdio>
#include <cstring>
#include <ADuCM360.h>
#include <hal/drivers/uart.h>
#include <hal/drivers/pwm.h>
#include <hal/drivers/ad8253.h>
#include <hal/drivers/adc.h>
#include <hal/drivers/encoder.h>
#include <hal/drivers/buzzer.h>
#include <hal/drivers/flash.h>
#include <hal/drivers/dac.h>

FILE *p_lcd, *p_uart, *p_flash, *p_dac, *p_adc, *p_pwm, *p_ad8253;

void initial_devices(void)
{
	setvbuf(stdout, nullptr, _IOLBF, 64);
	setvbuf(stdin, nullptr, _IOFBF, 16);
	setvbuf(stderr, nullptr, _IONBF, 0);

	NVIC_SetPriorityGrouping(6); //2 groups, each group have 4 subpriorities

	buzzer_open();

	p_flash = fopen("flash", "rb+");
	setvbuf(p_flash, nullptr, _IOFBF, sizeof(flash_file));

	flash_file setting;
	rewind(p_flash);
	fread(&setting, sizeof(flash_file), 1, p_flash);

	if (setting.baud_rate <= configure_file.max_baud_rate
			&& setting.baud_rate >= configure_file.min_baud_rate
			&& setting.cell_const <= configure_file.max_cell_const
			&& setting.cell_const >= configure_file.min_cell_const
			&& setting.frequency <= configure_file.max_freq
			&& setting.frequency >= configure_file.min_freq
			&& setting.temp_coef <= configure_file.max_temp_coef
			&& setting.temp_coef >= configure_file.min_temp_coef
			&& setting.voltage <= configure_file.max_voltage
			&& setting.voltage >= configure_file.min_voltage
			&& setting.rs485_address <= configure_file.max_rs485_address
			&& setting.rs485_address >= configure_file.min_rs485_address
			&& setting.setup <= configure_file.max_setup
			&& setting.setup >= configure_file.min_setup
			&& setting.hold <= configure_file.max_hold
			&& setting.hold >= configure_file.min_hold
			&& setting.lcd_uc1601s_br <= configure_file.max_lcd_uc1601s_br
			&& setting.lcd_uc1601s_br >= configure_file.min_lcd_uc1601s_br
			&& setting.lcd_uc1601s_pm <= configure_file.max_lcd_uc1601s_pm
			&& setting.lcd_uc1601s_pm >= configure_file.min_lcd_uc1601s_pm
			&& setting.lcd_uc1601s_tc <= configure_file.max_lcd_uc1601s_tc
			&& setting.lcd_uc1601s_tc >= configure_file.min_lcd_uc1601s_tc) //check flash_disk
	{
		beep(50); // disk ok
	}
	else // disk error
	{
		rewind(p_flash);
		fwrite(&default_setting, sizeof(flash_file), 1, p_flash);
		fflush(p_flash);

		beep(50, 50, 50, 50, 50, 50, 50, 50, 50);
	}

	p_uart = fopen("uart", "r");
	setvbuf(p_uart, nullptr, _IONBF, 0);

	p_lcd = fopen("lcd", "rb+");
	setvbuf(p_lcd, nullptr, _IOFBF, 16);

	p_dac = fopen("dac", "rb+");
	setvbuf(p_dac, nullptr, _IOFBF, sizeof(dac_file));

	p_pwm = fopen("pwm", "rb+");
	setvbuf(p_pwm, nullptr, _IOFBF, sizeof(pwm_file));

	p_ad8253 = fopen("ad8253", "rb+");
	setvbuf(p_ad8253, nullptr, _IOFBF, sizeof(ad8253_file));

	p_adc = fopen("adc", "rb");
	setvbuf(p_adc, nullptr, _IOFBF, sizeof(adc_file));

	encoder_open();
}
