/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <string.h>

// Definitions for BT8xx co processor command buffer
#define FT_DL_SIZE           (8*1024)  // 8kibiByte Speicher in RAM_DL für die Displayliste
#define BT_CMD_FIFO_SIZE     (4*1024)  // 4kibiByte Speicher in RAM_CMD
#define BT_CMD_SIZE          (4)       // 4 byte pro Befehl

// RAM-Speicherbereiche
#define RAM_G                    0x000000
#define RAM_DL                   0x300000
#define RAM_REG                  0x302000
#define RAM_CMD                  0x308000
#define RAM_FLASH                0x800000

// Graphics primitve
#define BITMAPS					  0x01
#define POINTS					  0x02
#define LINES					  0x03
#define LINE_STRIP				  0x04
#define EDGE_STRIP_R			  0x05
#define EDGE_STRIP_L			  0x06
#define EDGE_STRIP_A			  0x07
#define EDGE_STRIP_B			  0x08
#define RECTS					  0x09

// Graphics Engine Registers - FT81x Series Programmers Guide Section 3.1
// Addresses defined as offsets from the base address called RAM_REG and located at 0x302000
// Discussion: Defining this way leads to an additional add operation in code that can be avoided by defining
// these addresses as 32 bit values, but this is easily paid for in clarity and coorelation to documentation.
// Further, you can add defines together in code and allow the precompiler to do the add operation (as here).
#define REG_CSPREAD               0x68
#define REG_DITHER                0x60
#define REG_DLSWAP                0x54
#define REG_HCYCLE                0x2C
#define REG_HOFFSET               0x30
#define REG_HSIZE                 0x34
#define REG_HSYNC0                0x38
#define REG_HSYNC1                0x3C
#define REG_OUTBITS               0x5C
#define REG_PCLK                  0x70
#define REG_PCLK_POL              0x6C
#define REG_PLAY                  0x8C
#define REG_PLAYBACK_FORMAT       0xC4
#define REG_PLAYBACK_FREQ         0xC0
#define REG_PLAYBACK_LENGTH       0xB8
#define REG_PLAYBACK_LOOP         0xC8
#define REG_PLAYBACK_PLAY         0xCC
#define REG_PLAYBACK_READPTR      0xBC
#define REG_PLAYBACK_START        0xB4
#define REG_PWM_DUTY              0xD4
#define REG_ROTATE                0x58
#define REG_SOUND                 0x88
#define REG_SWIZZLE               0x64
#define REG_TAG                   0x7C
#define REG_TAG_X                 0x74
#define REG_TAG_Y                 0x78
#define REG_VCYCLE                0x40
#define REG_VOFFSET               0x44
#define REG_VOL_SOUND             0x84
#define REG_VOL_PB                0x80
#define REG_VSYNC0                0x4C
#define REG_VSYNC1                0x50
#define REG_VSIZE                 0x48


/*NOCH NICHT ÜBERPRÜFTE REGISTER
// Touch Screen Engine Registers - FT81x Series Programmers Guide Section 3.3
// Addresses defined as offsets from the base address called RAM_REG and located at 0x302000
#define REG_TOUCH_CONFIG          0x168
#define REG_TOUCH_TRANSFORM_A     0x150
#define REG_TOUCH_TRANSFORM_B     0x154
#define REG_TOUCH_TRANSFORM_C     0x158
#define REG_TOUCH_TRANSFORM_D     0x15C
#define REG_TOUCH_TRANSFORM_E     0x160
#define REG_TOUCH_TRANSFORM_F     0x164

// Resistive Touch Engine Registers - FT81x Series Programmers Guide Section 3.3.3 - Document confused
// Addresses defined as offsets from the base address called RAM_REG and located at 0x302000
#define REG_TOUCH_ADC_MODE        0x108
#define REG_TOUCH_CHARGE          0x10C
#define REG_TOUCH_DIRECT_XY       0x18C
#define REG_TOUCH_DIRECT_Z1Z2     0x190
#define REG_TOUCH_MODE            0x104
#define REG_TOUCH_OVERSAMPLE      0x114
#define REG_TOUCH_RAW_XY          0x11C
#define REG_TOUCH_RZ              0x120
#define REG_TOUCH_RZTHRESH        0x118
#define REG_TOUCH_SCREEN_XY       0x124
#define REG_TOUCH_SETTLE          0x110
#define REG_TOUCH_TAG             0x12C
#define REG_TOUCH_TAG_XY          0x128

// Capacitive Touch Engine Registers - FT81x Series Programmers Guide Section 3.3.4
// Addresses defined as offsets from the base address called RAM_REG and located at 0x302000
#define REG_CTOUCH_MODE           0x104
#define REG_CTOUCH_EXTEND         0x108
#define REG_CTOUCH_RAW_XY         0x11C
#define REG_CTOUCH_TOUCH_XY       0x124
#define REG_CTOUCH_TOUCH1_XY      0x11C
#define REG_CTOUCH_TOUCH2_XY      0x18C
#define REG_CTOUCH_TOUCH3_XY      0x190
#define REG_CTOUCH_TOUCH4_X       0x16C
#define REG_CTOUCH_TOUCH4_Y       0x120
#define REG_CTOUCH_TAG            0x12C
#define REG_CTOUCH_TAG1           0x134
#define REG_CTOUCH_TAG2           0x13C
#define REG_CTOUCH_TAG3           0x144
#define REG_CTOUCH_TAG4           0x14C
#define REG_CTOUCH_TAG_XY         0x128
#define REG_CTOUCH_TAG1_XY        0x130
#define REG_CTOUCH_TAG2_XY        0x138
#define REG_CTOUCH_TAG3_XY        0x140
#define REG_CTOUCH_TAG4_XY        0x148

*/

// Miscellaneous Registers - FT81x Series Programmers Guide Section 3.6 - Document inspecific about base address
// Addresses assumed to be defined as offsets from the base address called RAM_REG and located at 0x302000
#define REG_CPURESET              0x20
#define REG_PWM_HZ                0xD0
#define REG_INT_MASK              0xB0
#define REG_INT_EN                0xAC
#define REG_INT_FLAGS             0xA8
#define REG_GPIO                  0x94
#define REG_GPIO_DIR              0x90
#define REG_GPIOX                 0x9C
#define REG_GPIOX_DIR             0x98
#define REG_FREQUENCY             0x0C
#define REG_CLOCK                 0x08
#define REG_FRAMES                0x04
#define REG_ID                    0x00
#define REG_TRIM                  0x180
#define REG_SPI_WIDTH             0x188

// Co-processor Engine Registers - FT81x Series Programmers Guide Section 3.4
// Addresses defined as offsets from the base address called RAM_REG and located at 0x302000
#define REG_CMD_DL                0x100
#define REG_CMD_READ              0xF8
#define REG_CMDB_SPACE            0x574
#define REG_CMDB_WRITE            0x578
#define REG_COPRO_PATCH_PTR       0x7162
#define REG_CMD_WRITE             0xFC

//Alphabetdefines
#define T							84
#define E							69
#define X							88

	__STATIC_INLINE void DWT_Delay_us(volatile uint32_t microseconds)						//zum Erzeugen von Mikrosekundendelay
	{
	  uint32_t clk_cycle_start = DWT->CYCCNT;

	  /* Go to number of cycles for system */
	  microseconds *= (HAL_RCC_GetHCLKFreq() / 1000000);

	  /* Delay till end */
	  while ((DWT->CYCCNT - clk_cycle_start) < microseconds);
	}

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
SPI_HandleTypeDef hspi2;
DMA_HandleTypeDef hdma_spi2_tx;
DMA_HandleTypeDef hdma_spi2_rx;

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_SPI2_Init(void);


/*Variablendeklaration -------------------------------------------------------*/
int aufwr32_disp = 0;
uint32_t aktadress = 0;
uint16_t FifoWriteLocation = 0;

	//Speicherstrukturen welche zur Konstruktion des zu sendenden Arrays benutzt werden
	uint8_t vierByte[4];
	uint8_t dreiByte[3];
	uint8_t zweiByte[2];
	uint8_t einByte[1];
	uint8_t send[7];
	uint8_t send2[5];
	uint8_t send3[4];


/*Funktiondeklaration --------------------------------------------------------*/
void SSenable(void){				//SlaveSelectPin LOW setzen
	HAL_GPIO_WritePin(SlaveSelect_GPIO_Port, SlaveSelect_Pin, GPIO_PIN_RESET);
}
void SSdisable(void){				//SlaveSelectPin HIG setzne
	HAL_GPIO_WritePin(SlaveSelect_GPIO_Port, SlaveSelect_Pin, GPIO_PIN_SET);
}

void clear_send_array(void){		//send3 array auf 0 setzen
	send3[0]=0x00;
	send3[1]=0x00;
	send3[2]=0x00;
	send3[3]=0x00;
}

void clear_vierByte_array(void){	//vierByte array auf 0 setzen
	vierByte[0]=0x00;
	vierByte[1]=0x00;
	vierByte[2]=0x00;
	vierByte[3]=0x00;
}

void HostCommand(char comand[], uint8_t data){
/*uint8_t data wird nur bei Befehlen PINDRIVE und PIN_DA_STATE verwendet,
 * wenn keiner dieser zwei Befehle verwendet wird soll "data" beim Funktionsaufrauf
 * Wert 0x00 zugeweisen werden*/
	if (strcmp(comand,"ACTIVE" )==0){
		dreiByte[0]=0x00;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "STANDBY")==0){
		dreiByte[0]=0x41;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "SLEEP")==0){
		dreiByte[0]=0x42;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "PWRDOWN")==0){
		dreiByte[0]=0x43;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "CLKEXT")==0){
		dreiByte[0]=0x44;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "CLKINT")==0){
		dreiByte[0]=0x48;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "CLKSEL")==0){
		dreiByte[0]=0x61;
		dreiByte[1]=data;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "RST_PULSE")==0){
		dreiByte[0]=0x68;
		dreiByte[1]=0x00;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "PINDRIVE")==0){
		dreiByte[0]=0x70;
		dreiByte[1]=data;
		dreiByte[2]=0x00;
	} else if (strcmp(comand, "PIN_DA_STATE")==0){
		dreiByte[0]=0x71;
		dreiByte[1]=data;
		dreiByte[2]=0x00;
	}
	SSenable();
	DWT_Delay_us(1);
	HAL_SPI_Transmit_DMA(&hspi2, dreiByte, 3);
	DWT_Delay_us(1);
	SSdisable();
}

/*Allgemeiner Aufbau Schreibbefehl:
 * 10xx xxxx  xxxx xxxx  xxxx xxxx Datenbyte1  [Datenbyte2  Datenbyte3  Datenbyte4]
 * 1AddrByte  2AddrByte  3AddrByte
 *
 * Das erste Adressbyte muss mit 10 angeführt werden*/

void wr32(uint32_t address, uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3){			//Aufruf von wr32 über "RAM_Speicherbereich+Registername" Registername nicht als char notwendig
/*Schreibt vier Byte in der Reihenfolge: byte0, byte1, byte2, byte3*/
	dreiByte[0]=0xB0;
	dreiByte[1]=(address >> 8)&0xFF;
	dreiByte[2]=address&0xFF;
	send[0]=dreiByte[0];
	send[1]=dreiByte[1];
	send[2]=dreiByte[2];
	send[3]=byte0;
	send[4]=byte1;
	send[5]=byte2;
	send[6]=byte3;
	SSenable();
	DWT_Delay_us(1);
	HAL_SPI_Transmit_DMA(&hspi2, send, 7);
	DWT_Delay_us(1);
	SSdisable();
}

void wr16(uint32_t address, uint8_t byte0, uint8_t byte1){											//Aufruf von wr16 über "RAM_Speicherbereich+Registername" Registername nicht als char notwendig
/*Schreibt zwei Byte in der Reihenfolge: byte0, byte1*/
	dreiByte[0]=0xB0;
	dreiByte[1]=(address >> 8)&0xFF;
	dreiByte[2]=address&0xFF;
	send2[0]=dreiByte[0];
	send2[1]=dreiByte[1];
	send2[2]=dreiByte[2];
	send2[3]=byte0;
	send2[4]=byte1;
	SSenable();
	DWT_Delay_us(1);
	HAL_SPI_Transmit_DMA(&hspi2, send2, 5);
	DWT_Delay_us(1);
	SSdisable();
}

void wr8(uint32_t address, uint8_t byte0){															//Aufruf von wr8 über "RAM_Speicherbereich+Registername" Registername nicht als char notwendig
/*Schreibt ein Byte in der Reihenfolge: byte0*/
	dreiByte[0]=0xB0;
	dreiByte[1]=(address >> 8)&0xFF;
	dreiByte[2]=address&0xFF;
	send3[0]=dreiByte[0];
	send3[1]=dreiByte[1];
	send3[2]=dreiByte[2];
	send3[3]=byte0;
	SSenable();
	DWT_Delay_us(1);
	HAL_SPI_Transmit_DMA(&hspi2, send3, 4);
	DWT_Delay_us(1);
	SSdisable();
}


/*Allgemeiner Aufbaur Lese-Befehl
 * 00xx xxxx  xxxx xxxx  xxxx xxxx  0000 0000  Lesebyte1  Lesebyte2
 * 1AddrByte  2AddrByte  3AddrByte  DummyByte
 *
 * Die Addressbytes werden vom Master gesendet.
 * Das erste Adressbyte muss mit 00 angeführt werden*/

uint16_t rd16 (uint32_t address){
/*liest zwei Byte*/
	clear_send_array();
	dreiByte[0]=0x30;
	dreiByte[1]=(address >> 8)&0xFF;
	dreiByte[2]=address&0xFF;
	send3[0]=dreiByte[0];
	send3[1]=dreiByte[1];
	send3[2]=dreiByte[2];
	send3[3]=0x00;								//Dummybyte wird gesendet bevor Lesedaten empfangen werden
	SSenable();
	DWT_Delay_us(1);
	HAL_SPI_Transmit_DMA(&hspi2, send3, 4);		//senden von Addresse und Dummybyte
	HAL_SPI_Receive_DMA(&hspi2, zweiByte, 2);
	DWT_Delay_us(1);
	SSdisable();
	uint16_t erg16 = (zweiByte[0]<<8) | zweiByte[1];
	return erg16;
}

uint8_t rd8 (uint32_t address){
/*liest ein Byte*/
	clear_send_array();
	dreiByte[0]=0x30;
	dreiByte[1]=(address >> 8)&0xFF;
	dreiByte[2]=address&0xFF;
	send3[0]=dreiByte[0];
	send3[1]=dreiByte[1];
	send3[2]=dreiByte[2];
	send3[3]=0x00;								//Dummybyte wird gesendet bevor Lesedaten empfangen werden
	SSenable();
	DWT_Delay_us(1);
	HAL_SPI_Transmit_DMA(&hspi2, send3, 4);		//senden von Addresse und Dummybyte
	HAL_SPI_Receive_DMA(&hspi2, einByte, 1);
	DWT_Delay_us(1);
	SSdisable();
	uint8_t erg8 = einByte[0];
	return erg8;
}

	uint32_t DWT_Delay_Init(void) {
	  /* Disable TRC */
	  CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk; // ~0x01000000;
	  /* Enable TRC */
	  CoreDebug->DEMCR |=  CoreDebug_DEMCR_TRCENA_Msk; // 0x01000000;

	  /* Disable clock cycle counter */
	  DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk; //~0x00000001;
	  /* Enable  clock cycle counter */
	  DWT->CTRL |=  DWT_CTRL_CYCCNTENA_Msk; //0x00000001;

	  /* Reset the clock cycle counter value */
	  DWT->CYCCNT = 0;

	     /* 3 NO OPERATION instructions */
	     __ASM volatile ("NOP");
	     __ASM volatile ("NOP");
	  __ASM volatile ("NOP");

	  /* Check if clock cycle counter has started */
	     if(DWT->CYCCNT)
	     {
	       return 0; /*clock cycle counter started*/
	     }
	     else
	  {
	    return 1; /*clock cycle counter not started*/
	  }
	}

/*Grafikfunktionen---------------------------------------------------------------------*/
	/*CLEAR-Funktionen---------------------------------------------------------------------------------------------------------------------------*/
			uint32_t CLEAR(uint8_t byte0, uint8_t byte1, uint8_t byte2){
				//Bit 0: clear tag Buffer: if Bit is 1 means set to reset Value: Reset Value festgelegt durch Befehl CLEAR_TAG
				//Bit 1: clear stencil Buffer: if Bit is 1 means set to reset value: Reset value festgelegt durch den Befehl CLEAR_STENCIL
				//Bit2: clear color Buffer: if Bit is 1 means set to reset value: Reset value festtgelegt durch den Befehl CLEAR_COLOR_RGB
				clear_vierByte_array();
				vierByte[0]=0x26;
				vierByte[1]=0x00;
				vierByte[2]=0x00;
				vierByte[3]=(uint8_t) ((byte2<<2) | (byte1<<1) | (byte0));
				uint32_t zusammen = (vierByte[0]<<24) | (vierByte[1]<<16) | vierByte[2]<<8 | vierByte[3];
				return zusammen;
			}

			uint32_t CLEAR_COLOR_RGB(uint8_t red, uint8_t green, uint8_t blue){
				//legt die Werte für Rot, Grün und Blau fest wenn der color buffer ist geleert
				clear_vierByte_array();
				vierByte[0]=0x02;
				vierByte[1]=red;
				vierByte[2]=blue;
				vierByte[3]=green;
				uint32_t zusammen = (vierByte[0]<<24) | (vierByte[1]<<16) | (vierByte[2]<<8) | vierByte[3];
				return zusammen;
			}

			void CLEAR_STENCIL(uint8_t byte0){
				//legt Wert nach dem stencil-Buffer geleert wurde fest
				clear_vierByte_array();
				vierByte[0]=0x11;
				vierByte[1]=0x00;
				vierByte[2]=0x00;
				vierByte[3]=byte0;
				//wr32_displaylist(RAM_DL + FifoWriteLocation,vierByte);
			}

			void CLEAR_TAG(uint8_t byte0){
				//legt Wert fest nach dem tag-buffer geleert wurde fest
				clear_vierByte_array();
				vierByte[0]=0x12;
				vierByte[1]=0x00;
				vierByte[2]=0x00;
				vierByte[3]=byte0;
				//wr32_displaylist(RAM_DL + FifoWriteLocation,vierByte);
			}
	/*Display-Funktionen---------------------------------------------------------------------------------------------------------------------------*/
			uint32_t DISPLAY(void){
				//zeigt das Ende der Displayliste an
				//alle Befefehle danach werden ignoriert
				clear_vierByte_array();
				vierByte[0]=0x00;
				vierByte[1]=0x00;
				vierByte[2]=0x00;
				vierByte[3]=0x00;
				uint32_t zusammen = (vierByte[0]<<24) | (vierByte[1]<<16) | vierByte[2]<<8 | vierByte[3];
				return zusammen;
			}

			uint32_t VERTEX2II(unsigned short x, unsigned short y, short handle, int buchstabe){
				uint32_t zusammen=(0x2<<30) | (x<<21) | (y<<12) | (handle<<7) | buchstabe;
				clear_vierByte_array();
				vierByte[0]=(zusammen>>24)&0xff;
				vierByte[1]=(zusammen>>16)&0xff;
				vierByte[2]=(zusammen>>8)&0xff;
				vierByte[3]=zusammen&0xff;
				return zusammen;
			}

			void END(void){
				clear_vierByte_array();
				vierByte[0]=0x21;
				vierByte[1]=0x00;
				vierByte[2]=0x00;
				vierByte[3]=0x00;
				//wr32_displaylist(RAM_DL + FifoWriteLocation,vierByte);
			}



void DispInit(void){
	HostCommand("ACTIVE", 0x00);																//send host command "ACTIVE" to wake up	=> überprüft
	HostCommand("RST_PULSE", 0x00);																//send host command "RST_PULSE" to reset => überprüft
	while(0x7C != rd8(RAM_REG+REG_ID));
	while(0x0000 != rd16(RAM_REG+REG_CPURESET));												//check if EVE is in working status
	wr32(RAM_REG + REG_FREQUENCY, 0x03, 0x93, 0x87, 0x00);										//configure system clock to 60 MHz => überprüft

	/* Configure display registers*/
	wr16(RAM_REG+REG_HCYCLE, 0x03, 0xA0);
	wr16(RAM_REG+REG_HOFFSET, 0x00, 0x58);
	wr16(RAM_REG+REG_HSYNC0, 0x00, 0x00);
	wr16(RAM_REG+REG_HSYNC1, 0x00, 0x30);
	wr16(RAM_REG+REG_VCYCLE, 0x02, 0x0D);
	wr16(RAM_REG+REG_VOFFSET, 0x00, 0x20);
	wr16(RAM_REG+REG_VSYNC0, 0x00, 0x00);
	wr16(RAM_REG+REG_VSYNC1, 0x00, 0x03);
	wr8(RAM_REG+REG_SWIZZLE, 0x00);
	wr8(RAM_REG+REG_PCLK_POL, 0x01);
	wr8(RAM_REG+REG_CSPREAD, 0x00);
	wr16(RAM_REG+REG_HSIZE, 0x03, 0x20);
	wr16(RAM_REG+REG_VSIZE, 0x01, 0xE0);

	uint32_t ergCCRGB = CLEAR_COLOR_RGB(0,0,255);
	uint32_t ergC = CLEAR(1,1,1);
	uint32_t ergD = DISPLAY();
	wr32(RAM_DL+0, (ergCCRGB>>24)&0xFF, (ergCCRGB>>16)&0xFF, (ergCCRGB>>8)&0xFF, ergCCRGB&0xFF);
	wr32(RAM_DL+4, (ergC>>24)&0xFF, (ergC>>16)&0xFF, (ergC>>8)&0xFF, ergC&0xFF);
	wr32(RAM_DL+8, (ergD>>24)&0xFF, (ergD>>16)&0xFF, (ergD>>8)&0xFF, ergD&0xFF);

	wr8(REG_DLSWAP,0x02);

	/*Enable backlight of display panel*/
	wr8(RAM_REG + REG_GPIO_DIR, 0xff);
	wr8(RAM_REG + REG_GPIO, 0xff);
	wr8(RAM_REG + REG_PCLK, 0x02);																//Configure the PCLK divisor to 2, i.e. PCLK = System CLK/2 => überprüft
}

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE B_EGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_ADC1_Init();
  MX_SPI2_Init();
  SSdisable();
  DWT_Delay_Init();
  DispInit();
  //CMD_DL_eins();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  rd8(RAM_REG + REG_ID);
	/*if (start==1){
	HAL_ADC_START_ADC
	}*/
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = DISABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = DISABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief SPI2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_SPI2_Init(void)
{

  /* USER CODE BEGIN SPI2_Init 0 */

  /* USER CODE END SPI2_Init 0 */

  /* USER CODE BEGIN SPI2_Init 1 */

  /* USER CODE END SPI2_Init 1 */
  /* SPI2 parameter configuration*/
  hspi2.Instance = SPI2;
  hspi2.Init.Mode = SPI_MODE_MASTER;
  hspi2.Init.Direction = SPI_DIRECTION_2LINES;
  hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
  hspi2.Init.NSS = SPI_NSS_SOFT;
  hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
  hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi2.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN SPI2_Init 2 */

  /* USER CODE END SPI2_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA1_CLK_ENABLE();
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA1_Stream3_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream3_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream3_IRQn);
  /* DMA1_Stream4_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOB, SlaveSelect_Pin|RESET_Display_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : Display_Interrupt_Pin */
  GPIO_InitStruct.Pin = Display_Interrupt_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(Display_Interrupt_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pins : SlaveSelect_Pin RESET_Display_Pin */
  GPIO_InitStruct.Pin = SlaveSelect_Pin|RESET_Display_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */