#include "main.h"
#include "lcd.h"
#include "SST25VF016B.h"

extern SPI_HandleTypeDef hspi1;

void SST25VF016B_run_test(void)
{
	DISPLAY_CLEAR;
	display_write_data_seq("SST25VF016B Flas");

	HAL_StatusTypeDef op_result;
	size_t err_count = 0;

	uint8_t tx_buffer[8] = {0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
	uint8_t rx_buffer[9];
	rx_buffer[8] = '\0';

	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);
	HAL_Delay(50);
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_RESET);

	for (size_t t = 0; t < 5; t++) {
		op_result = HAL_SPI_TransmitReceive(&hspi1, tx_buffer, rx_buffer, 8, 2000);

		if (op_result) {
			err_count++;

			DISPLAY_CLEAR;
			display_write_data_seq("SST25VF016B Flas");

			DISPLAY_SET_CURSOR(1, 0);
			display_write_data_byte('1' + t);
			display_write_data_seq("/5 ");

			switch (op_result) {
			case HAL_OK:
				break;
			case HAL_ERROR:
				display_write_data_seq("ERROR");
				break;
			case HAL_BUSY:
				display_write_data_seq("BUSY");
				break;
			case HAL_TIMEOUT:
				display_write_data_seq("TIMEOUT");
				break;
			}

			HAL_Delay(2000);
		} else {
			break;
		}
	}

	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);

	DISPLAY_CLEAR;
	display_write_data_seq("SST25VF016B Flas");

	if (err_count) {
		DISPLAY_SET_CURSOR(1, 1);
		display_write_data_byte('0' + err_count % 10);
		display_write_data_seq(" Errors");
	} else {
		for (size_t i = 0; i < 4; i += 2) {
			// odd reads MUST result in 0xBF
			if (rx_buffer[4+i] != 0xBF) {
				DISPLAY_SET_CURSOR(1, 0);
				display_write_data_byte('B');
				display_write_data_byte('1'+i);
				display_write_data_seq(" WRONG");
				goto write_retrieved_data;
			}
		}

		for (size_t i = 1; i < 4; i += 2) {
			// even reads MUST result in 0x41
			if (rx_buffer[4+i] != 0x41) {
				DISPLAY_SET_CURSOR(1, 0);
				display_write_data_byte('B');
				display_write_data_byte('1'+i);
				display_write_data_seq(" WRONG");
				goto write_retrieved_data;
			}
		}

		DISPLAY_SET_CURSOR(1, 1);
		display_write_data_seq("OK");
	}

	write_retrieved_data:
	DISPLAY_SET_CURSOR(1, 12);
	display_write_data_seq((char *) &(rx_buffer[4]));

	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_7, GPIO_PIN_SET);
}
