some changes. and cleanup

This commit is contained in:
lucordes 2025-07-12 17:22:17 +02:00
parent de2abc2cc7
commit dfbfc96e38
8 changed files with 488 additions and 673 deletions

View File

@ -63,14 +63,10 @@ void Error_Handler(void);
#define LED_BLUE_GPIO_Port GPIOC #define LED_BLUE_GPIO_Port GPIOC
#define DISPLAY_CS_Pin GPIO_PIN_4 #define DISPLAY_CS_Pin GPIO_PIN_4
#define DISPLAY_CS_GPIO_Port GPIOA #define DISPLAY_CS_GPIO_Port GPIOA
#define TOUCH_CS_Pin GPIO_PIN_1
#define TOUCH_CS_GPIO_Port GPIOB
#define DISPLAY_DC_Pin GPIO_PIN_2 #define DISPLAY_DC_Pin GPIO_PIN_2
#define DISPLAY_DC_GPIO_Port GPIOB #define DISPLAY_DC_GPIO_Port GPIOB
#define DISPLAY_RES_Pin GPIO_PIN_10 #define DISPLAY_RES_Pin GPIO_PIN_10
#define DISPLAY_RES_GPIO_Port GPIOA #define DISPLAY_RES_GPIO_Port GPIOA
#define TOUCH_IRQ_Pin GPIO_PIN_5
#define TOUCH_IRQ_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */ /* USER CODE BEGIN Private defines */

View File

@ -56,6 +56,7 @@ void TIM2_IRQHandler(void);
void SPI1_IRQHandler(void); void SPI1_IRQHandler(void);
void DMA2_Stream0_IRQHandler(void); void DMA2_Stream0_IRQHandler(void);
void DMA2_Stream3_IRQHandler(void); void DMA2_Stream3_IRQHandler(void);
void USART6_IRQHandler(void);
/* USER CODE BEGIN EFP */ /* USER CODE BEGIN EFP */
/* USER CODE END EFP */ /* USER CODE END EFP */

View File

@ -23,11 +23,10 @@
/* Private includes ----------------------------------------------------------*/ /* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */ /* USER CODE BEGIN Includes */
//#include "ili9341.h" //#include "ili9341.h"
//#include "ili9341_touch.h"
#include "ILI9341_STM32_Driver.h" #include "ILI9341_STM32_Driver.h"
#include "ILI9341_GFX.h" #include "ILI9341_GFX.h"
#include "ili9341_touch.h" #include "snake.h"
//#include "xpt2046.h"
/* USER CODE END Includes */ /* USER CODE END Includes */
@ -50,7 +49,6 @@
I2C_HandleTypeDef hi2c1; I2C_HandleTypeDef hi2c1;
SPI_HandleTypeDef hspi1; SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi2;
DMA_HandleTypeDef hdma_spi1_rx; DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx; DMA_HandleTypeDef hdma_spi1_tx;
@ -74,18 +72,11 @@ const osThreadAttr_t draw_attributes = {
.stack_size = 512 * 4, .stack_size = 512 * 4,
.priority = (osPriority_t) osPriorityLow, .priority = (osPriority_t) osPriorityLow,
}; };
/* Definitions for reactiongame */ /* Definitions for menu */
osThreadId_t reactiongameHandle; osThreadId_t menuHandle;
const osThreadAttr_t reactiongame_attributes = { const osThreadAttr_t menu_attributes = {
.name = "reactiongame", .name = "menu",
.stack_size = 128 * 4, .stack_size = 256 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for gamepicker */
osThreadId_t gamepickerHandle;
const osThreadAttr_t gamepicker_attributes = {
.name = "gamepicker",
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow, .priority = (osPriority_t) osPriorityLow,
}; };
/* Definitions for presses */ /* Definitions for presses */
@ -107,16 +98,14 @@ void SystemClock_Config(void);
static void MX_GPIO_Init(void); static void MX_GPIO_Init(void);
static void MX_DMA_Init(void); static void MX_DMA_Init(void);
static void MX_SPI1_Init(void); static void MX_SPI1_Init(void);
static void MX_SPI2_Init(void);
static void MX_TIM1_Init(void); static void MX_TIM1_Init(void);
static void MX_TIM4_Init(void); static void MX_TIM4_Init(void);
static void MX_TIM5_Init(void); static void MX_TIM5_Init(void);
static void MX_USART6_UART_Init(void); static void MX_USART6_UART_Init(void);
static void MX_I2C1_Init(void); static void MX_I2C1_Init(void);
void StartTouchHist(void *argument);
void snakegame(void *argument); void snakegame(void *argument);
void startreactiongame(void *argument); void handle_menu(void *argument);
void gamepicker_entry(void *argument);
/* USER CODE BEGIN PFP */ /* USER CODE BEGIN PFP */
@ -125,11 +114,7 @@ void gamepicker_entry(void *argument);
/* Private user code ---------------------------------------------------------*/ /* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */ /* USER CODE BEGIN 0 */
#define touchbuffersize 50
struct {
int x[touchbuffersize];
int y[touchbuffersize];
} touchcoord;
void titlescreen() { void titlescreen() {
ILI9341_FillScreen(WHITE); ILI9341_FillScreen(WHITE);
@ -142,367 +127,65 @@ void titlescreen() {
//ILI9341_WriteString(320 / 2 + 100, 240 / 2, str, Font_11x18, //ILI9341_WriteString(320 / 2 + 100, 240 / 2, str, Font_11x18,
//ILI9341_MAGENTA, ILI9341_WHITE); //ILI9341_MAGENTA, ILI9341_WHITE);
} }
#define FLASH_USER_ADDR ((uint32_t)0x0803F000) // Last 4 KB
void Flash_Write_HighScore(uint32_t highscore) {
HAL_FLASH_Unlock();
// Erase the sector first
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t PageError = 0;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; #define RX_BUFFER_SIZE 1
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; #define LINE_BUFFER_SIZE 128
EraseInitStruct.Sector = FLASH_SECTOR_5;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) { uint8_t rx_buffer[RX_BUFFER_SIZE];
// Handle error char line_buffer[LINE_BUFFER_SIZE];
return; uint16_t line_pos = 0;
} void process_line(const char *line) {
if (strncmp(line, "ABS:", 4) == 0) {
// Program the word char axis[32];
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_USER_ADDR, highscore) int value;
!= HAL_OK) { if (sscanf(line, "ABS:%31[^:]:%d:", axis, &value) == 2) {
// Handle error // Handle axis input
} if (strcmp(axis, "ABS_X") == 0) {
// Do something with X axis
HAL_FLASH_Lock();
}
uint32_t Flash_Read_HighScore(void) {
return *(uint32_t*) FLASH_USER_ADDR;
}
struct Snake {
// Snake head coordinates (x-axis, y-axis)
int x, y;
// Food coordinates
int fruitCordX, fruitCordY;
// Player's score
int playerScore;
// Tail coordinates
int TailX[100], TailY[100];
// Tail length
int TailLen;
// Movement direction
enum Direction {
STOP = 0, LEFT, RIGHT, UP, DOWN
} Dir;
int gamesizewidth; //number of " pixels " in the horizontal
int gamesizeheight;
int TailPendingDeletionX;
int TailPendingDeletionY;
int TailGrowPending; // Delay tail growth by one frame
// Game over flag
int isGameOver;
} snake;
// Function to initialize game variables
void GameInit() {
snake.gamesizeheight = 6;
snake.gamesizewidth = 8;
snake.isGameOver = 0;
snake.Dir = RIGHT;
snake.x = 1; //snake.gamesizewidth / 2;
snake.y = 1; //snake.gamesizeheight / 2;
snake.fruitCordX = 2; //rand() % snake.gamesizewidth;
snake.fruitCordY = 1; //rand() % snake.gamesizeheight;
snake.playerScore = 0;
snake.TailLen = 0;
snake.TailGrowPending = 0;
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_FillScreen(WHITE);
osMutexRelease(displayHandle);
}
}
// Function for updating the game state
void UpdateGame() {
char dir;
// check the queue non blocking
osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL, 0); // 0 = no wait
if (status == osOK) {
switch (dir) {
case 'L':
snake.Dir = LEFT;
break;
case 'R':
snake.Dir = RIGHT;
break;
case 'U':
snake.Dir = UP;
break;
case 'D':
snake.Dir = DOWN;
break;
}
}
if (!snake.TailGrowPending) {
if (snake.TailLen > 0) {
snake.TailPendingDeletionX = snake.TailX[snake.TailLen - 1];
snake.TailPendingDeletionY = snake.TailY[snake.TailLen - 1];
} else {
snake.TailPendingDeletionX = snake.x;
snake.TailPendingDeletionY = snake.y;
}
}
snake.TailGrowPending = 0;
// tail movement
if (snake.TailLen > 0) {
for (int i = snake.TailLen - 1; i > 0; i--) {
snake.TailX[i] = snake.TailX[i - 1];
snake.TailY[i] = snake.TailY[i - 1];
}
snake.TailX[0] = snake.x;
snake.TailY[0] = snake.y;
}
switch (snake.Dir) {
case LEFT:
snake.x--;
break;
case RIGHT:
snake.x++;
break;
case UP:
snake.y--;
break;
case DOWN:
snake.y++;
break;
}
// Checks for snake's collision with the wall
if (snake.x >= snake.gamesizewidth || snake.x < 0
|| snake.y >= snake.gamesizeheight || snake.y < 0)
snake.isGameOver = 1;
// Checks for collision with the tail (o)
for (int i = 0; i < snake.TailLen; i++) {
if (snake.TailX[i] == snake.x && snake.TailY[i] == snake.y)
snake.isGameOver = 1;
}
// Checks for snake's collision with the food (#)
if (snake.x == snake.fruitCordX && snake.y == snake.fruitCordY) {
snake.playerScore += 10;
snake.fruitCordX = 0; //rand() % snake.gamesizewidth;
snake.fruitCordY = 0; //rand() % snake.gamesizeheight;
snake.TailLen++;
snake.TailX[snake.TailLen - 1] = snake.x;
snake.TailY[snake.TailLen - 1] = snake.y;
snake.TailGrowPending = 1;
//snake.TailPendingDeletionX = -1;
}
if (snake.isGameOver) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
if (Flash_Read_HighScore() > snake.playerScore) {
char str[50];
sprintf(str, "Highscore Remains: %lu", Flash_Read_HighScore());
ILI9341_DrawText(str, FONT3, 320 / 2 - 70, 240 / 2, BLACK,
WHITE);
// ILI9341_WriteString(320 / 2 - 70, 240 / 2, str, Font_11x18,
//ILI9341_MAGENTA, ILI9341_WHITE);
} else {
char str[50];
sprintf(str, "New Highscore: %lu", snake.playerScore);
//ILI9341_WriteString(320 / 2 - 70, 240 / 2, str, Font_11x18,
//ILI9341_MAGENTA, ILI9341_WHITE);
ILI9341_DrawText(str, FONT3, 320 / 2 - 70, 240 / 2, BLACK,
WHITE);
Flash_Write_HighScore(snake.playerScore);
}
osMutexRelease(displayHandle);
}
}
}
// Function to handle user UserInput
int prevpressed;
void UserInput() {
// Checks if a key is pressed or not
//case 'a':
// snake.Dir = LEFT;
uint16_t x, y;
x = getX();
y = getY();
if (x != 0 || y != 0) {
int a = x;
}
int ia = HAL_GPIO_ReadPin(ILI9341_TOUCH_IRQ_GPIO_Port,
ILI9341_TOUCH_IRQ_Pin) == GPIO_PIN_RESET;
if (ILI9341_TouchGetCoordinates(&x, &y)) { // Only act if touch detected
if ((x == 123 || x == 124 || x == 125 || x == 126) && y == 0) {
} else {
for (int i = 0; i < touchbuffersize - 1; i++) {
touchcoord.x[i] = touchcoord.x[i + 1];
touchcoord.y[i] = touchcoord.y[i + 1];
//}
touchcoord.x[touchbuffersize - 1] = x;
touchcoord.y[touchbuffersize - 1] = y;
}
char dir;
if (x < 107) {
dir = 'L'; // Left
} else if (x > 213) {
dir = 'R'; // Right
} else if (y > 120) {
dir = 'U'; // Up
} else {
dir = 'D'; // Down
}
dir = 'R';
// Send the direction to the queue
//if (!prevpressed && ILI9341_TouchPressed()) {
} else if (strcmp(axis, "ABS_Y") == 0) {
// Do something with Y axis
}
}
} else if (strncmp(line, "KEY:", 4) == 0) {
char key[32];
int state;
if (sscanf(line, "KEY:%31[^:]:%d:", key, &state) == 2) {
// Handle button press/release
char dir;
dir=key[0];
osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0, 0); osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0, 0);
if (status != osOK) { if (status != osOK) {
// Optional: Handle error // Optional: Handle error
} }
} if (key[0]=='D' && state == 1) {
// Button pressed
prevpressed = 1; } else if (key[0]=='D' && state == 0) {
//} else { // Button released
prevpressed = 0; }
//give illegal coords }
//if it is already we can skip it }
if (touchcoord.x[0] != ILI9341_SCREEN_WIDTH) { //is the last buffer coord illegal?
for (int i = 0; i < touchbuffersize - 1; i++) {
touchcoord.x[i] = touchcoord.x[i + 1];
touchcoord.y[i] = touchcoord.y[i + 1];
}
touchcoord.x[touchbuffersize - 1] = ILI9341_SCREEN_WIDTH;
touchcoord.y[touchbuffersize - 1] = ILI9341_SCREEN_WIDTH;
}
}
} }
// Function for creating the game board & rendering void UART_CALLBACK() {
void GameRender() { char ch = rx_buffer[0];
// Creating top walls if (ch == '\r') {
// Creating side walls // ignore
//ILI9341_FillRectangle(j, i, ILI9341_WIDTH/snake.gamesizewidth, ILI9341_HEIGHT/snake.gamesizeheight, ILI9341_YELLOW); } else if (ch == '\n') {
//ILI9341_FillScreen(MAGENTA); //line_buffer[line_pos] = '\0';
for (int x = 0; x < snake.gamesizewidth; x++) { if(line_buffer[1]=='K'||line_buffer[1]=='A'){
for (int y = 0; y <= snake.gamesizeheight; y++) { process_line(&line_buffer[1]);
}else{
if (x == snake.x && y == snake.y) { process_line(line_buffer);
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
BLACK);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_BLACK);
osMutexRelease(displayHandle);
}
}
//cout << "O";
// Creating the sanke's food with '#'
else if (x == snake.fruitCordX && y == snake.fruitCordY) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
RED);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight, ILI9341_RED);
osMutexRelease(displayHandle);
}
}
//cout << "#";
else if (snake.TailLen >= 0) {
for (int i = 0; i < snake.TailLen; i++) {
if (snake.TailX[0] == x && snake.TailY[0] == y) {
if (osMutexAcquire(displayHandle, osWaitForever)
== osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH)
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT)
/ snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH)
/ snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT)
/ snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
GREEN);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_GREEN);
osMutexRelease(displayHandle);
}
}
}
}
if (snake.TailPendingDeletionX == x
&& snake.TailPendingDeletionY == y) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
WHITE);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_WHITE);
osMutexRelease(displayHandle);
}
}
} }
line_pos = 0;
} else if (line_pos < LINE_BUFFER_SIZE - 1) {
line_buffer[line_pos++] = ch;
} }
HAL_UART_Receive_IT(&huart6, rx_buffer, RX_BUFFER_SIZE);
} }
/* USER CODE END 0 */ /* USER CODE END 0 */
@ -538,7 +221,6 @@ int main(void)
MX_GPIO_Init(); MX_GPIO_Init();
MX_DMA_Init(); MX_DMA_Init();
MX_SPI1_Init(); MX_SPI1_Init();
MX_SPI2_Init();
MX_TIM1_Init(); MX_TIM1_Init();
MX_TIM4_Init(); MX_TIM4_Init();
MX_TIM5_Init(); MX_TIM5_Init();
@ -549,7 +231,7 @@ int main(void)
ILI9341_SetRotation(SCREEN_HORIZONTAL_1); ILI9341_SetRotation(SCREEN_HORIZONTAL_1);
ILI9341_FillScreen(MAGENTA); ILI9341_FillScreen(MAGENTA);
//void XPT2046_Init(); //void XPT2046_Init();
//Flash_Write_HighScore(100);
/* USER CODE END 2 */ /* USER CODE END 2 */
/* Init scheduler */ /* Init scheduler */
@ -580,16 +262,13 @@ int main(void)
/* Create the thread(s) */ /* Create the thread(s) */
/* creation of touchhistory */ /* creation of touchhistory */
touchhistoryHandle = osThreadNew(StartTouchHist, NULL, &touchhistory_attributes); //touchhistoryHandle = osThreadNew(StartTouchHist, NULL, &touchhistory_attributes);
/* creation of draw */ /* creation of draw */
drawHandle = osThreadNew(snakegame, NULL, &draw_attributes); drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
/* creation of reactiongame */ /* creation of menu */
//reactiongameHandle = osThreadNew(startreactiongame, NULL, &reactiongame_attributes); menuHandle = osThreadNew(handle_menu, NULL, &menu_attributes);
/* creation of gamepicker */
//gamepickerHandle = osThreadNew(gamepicker_entry, NULL, &gamepicker_attributes);
/* USER CODE BEGIN RTOS_THREADS */ /* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */ /* add threads, ... */
@ -772,44 +451,6 @@ static void MX_SPI1_Init(void)
} }
/**
* @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_64;
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 */
}
/** /**
* @brief TIM1 Initialization Function * @brief TIM1 Initialization Function
* @param None * @param None
@ -1008,6 +649,8 @@ static void MX_USART6_UART_Init(void)
Error_Handler(); Error_Handler();
} }
/* USER CODE BEGIN USART6_Init 2 */ /* USER CODE BEGIN USART6_Init 2 */
uint8_t rx_byte;
HAL_UART_Receive_IT(&huart6, &rx_byte, 1);
/* USER CODE END USART6_Init 2 */ /* USER CODE END USART6_Init 2 */
@ -1056,7 +699,7 @@ static void MX_GPIO_Init(void)
HAL_GPIO_WritePin(GPIOA, DISPLAY_CS_Pin|DISPLAY_RES_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, DISPLAY_CS_Pin|DISPLAY_RES_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */ /*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, TOUCH_CS_Pin|DISPLAY_DC_Pin, GPIO_PIN_RESET); HAL_GPIO_WritePin(DISPLAY_DC_GPIO_Port, DISPLAY_DC_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED_BLUE_Pin */ /*Configure GPIO pin : LED_BLUE_Pin */
GPIO_InitStruct.Pin = LED_BLUE_Pin; GPIO_InitStruct.Pin = LED_BLUE_Pin;
@ -1072,18 +715,12 @@ static void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : TOUCH_CS_Pin DISPLAY_DC_Pin */ /*Configure GPIO pin : DISPLAY_DC_Pin */
GPIO_InitStruct.Pin = TOUCH_CS_Pin|DISPLAY_DC_Pin; GPIO_InitStruct.Pin = DISPLAY_DC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_Init(DISPLAY_DC_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : TOUCH_IRQ_Pin */
GPIO_InitStruct.Pin = TOUCH_IRQ_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(TOUCH_IRQ_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */ /* USER CODE BEGIN MX_GPIO_Init_2 */
@ -1101,29 +738,7 @@ static void MX_GPIO_Init(void)
* @retval None * @retval None
*/ */
/* USER CODE END Header_StartTouchHist */ /* USER CODE END Header_StartTouchHist */
void StartTouchHist(void *argument)
{
/* USER CODE BEGIN 5 */
/* Infinite loop */
for (;;) {
UserInput();
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// Mutex successfully locked
ILI9341_DrawPixel(touchcoord.x[touchbuffersize - 1],
touchcoord.y[touchbuffersize - 1], MAGENTA);
ILI9341_DrawPixel(touchcoord.x[0], touchcoord.y[0], MAGENTA);
//ILI9341_DrawPixel(touchcoord.x[touchbuffersize - 1],
// touchcoord.y[touchbuffersize - 1], ILI9341_MAGENTA);
// ILI9341_DrawPixel(touchcoord.x[0], touchcoord.y[0], ILI9341_WHITE);
osMutexRelease(displayHandle);
}
osDelay(100);
}
/* USER CODE END 5 */
}
/* USER CODE BEGIN Header_snakegame */ /* USER CODE BEGIN Header_snakegame */
/** /**
@ -1149,7 +764,10 @@ void snakegame(void *argument)
vTaskDelay(1000); vTaskDelay(1000);
//ILI9341_FillScreen(timer%0xFFFF); if(isGameOver()){
vTaskDelay(2000);
GameInit();
}
UpdateGame(); UpdateGame();
} }
@ -1157,112 +775,22 @@ void snakegame(void *argument)
/* USER CODE END snakegame */ /* USER CODE END snakegame */
} }
/* USER CODE BEGIN Header_startreactiongame */ /* USER CODE BEGIN Header_handle_menu */
/** /**
* @brief Function implementing the reactiongame thread. * @brief Function implementing the menu thread.
* @param argument: Not used * @param argument: Not used
* @retval None * @retval None
*/ */
/* USER CODE END Header_startreactiongame */ /* USER CODE END Header_handle_menu */
void startreactiongame(void *argument) void handle_menu(void *argument)
{ {
/* USER CODE BEGIN startreactiongame */ /* USER CODE BEGIN handle_menu */
/* Infinite loop */ /* Infinite loop */
uint32_t lasttimestamp = osKernelGetTickCount(); for(;;)
for (;;) { {
int a = rand() % 4000; osDelay(1);
osDelay(1000 + a); }
char dir; /* USER CODE END handle_menu */
char str[50];
// add the check for clicking too early. add the message clicked too early
// if (osMessageQueueGet(pressesHandle, &dir, NULL, 0) != osOK) { // Check if someone pressed during the delay → early press
//
// if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// ILI9341_FillScreen(ILI9341_GREEN);
// osMutexRelease(displayHandle);
// }
// lasttimestamp = osKernelGetTickCount();
// // check the queue blocking
// osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL,
// osWaitForever);
//
// int timediff = osKernelGetTickCount() - lasttimestamp;
// sprintf(str, "Time %d", timediff);
// if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// if (dir == 'L') {
// ILI9341_WriteString(320 / 2 - 100, 240 / 2, str, Font_11x18,
// ILI9341_MAGENTA, ILI9341_WHITE);
// }
// if (dir == 'R') {
// ILI9341_WriteString(320 / 2 + 100, 240 / 2, str, Font_11x18,
// ILI9341_MAGENTA, ILI9341_WHITE);
// }
// osMutexRelease(displayHandle);
// }
// } else {
// sprintf(str, "Pressed too early");
// if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// if (dir == 'L') {
// ILI9341_WriteString(320 / 2 - 100, 240 / 2, str, Font_11x18,
// ILI9341_MAGENTA, ILI9341_WHITE);
// }
// if (dir == 'R') {
// ILI9341_WriteString(320 / 2 + 100, 240 / 2, str, Font_11x18,
// ILI9341_MAGENTA, ILI9341_WHITE);
// }
// osMutexRelease(displayHandle);
// }
//
// }
// osDelay(1000);
// if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// ILI9341_FillScreen(ILI9341_WHITE);
// osMutexRelease(displayHandle);
// }
// //clear the queue
// while (osMessageQueueGet(pressesHandle, &dir, NULL, 0) == osOK) {
// // Discarding messages one by one
// }
}
/* USER CODE END startreactiongame */
}
/* USER CODE BEGIN Header_gamepicker_entry */
/**
* @brief Function implementing the gamepicker thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_gamepicker_entry */
void gamepicker_entry(void *argument)
{
/* USER CODE BEGIN gamepicker_entry */
/* Infinite loop */
for (;;) {
osDelay(1);
titlescreen(); // Render title screen
char dir;
// Wait for input (blocking)
osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL,
osWaitForever);
if (status == osOK) {
if (dir == 'L') {
drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
osThreadExit(); // Game Manager exits or waits for signal to restart
} else if (dir == 'R') {
reactiongameHandle = osThreadNew(startreactiongame, NULL,
&reactiongame_attributes);
osThreadExit();
} else {
// not implemeted
}
}
}
/* USER CODE END gamepicker_entry */
} }
/** /**

285
Core/Src/snake.c Normal file
View File

@ -0,0 +1,285 @@
#include "main.h" // HAL, ILI9341, CMSIS-RTOS handles
#include "cmsis_os.h" // RTOS types like osMutexAcquire, osMessageQueueGet
#include "stdlib.h" // For rand()
#include "stdio.h" // For sprintf()
#include "snake.h" // Your own header for declarations
#include "ILI9341_STM32_Driver.h"
#include "fonts.h"
struct Snake snake; // define the global variable here
#define FLASH_USER_ADDR ((uint32_t)0x0803F000) // Last 4 KB
void Flash_Write_HighScore(uint32_t highscore) {
HAL_FLASH_Unlock();
// Erase the sector first
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t PageError = 0;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FLASH_SECTOR_5;
EraseInitStruct.NbSectors = 1;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &PageError) != HAL_OK) {
// Handle error
return;
}
// Program the word
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, FLASH_USER_ADDR, highscore)
!= HAL_OK) {
// Handle error
}
HAL_FLASH_Lock();
}
uint32_t Flash_Read_HighScore(void) {
return *(uint32_t*) FLASH_USER_ADDR;
}
// Function to initialize game variables
void GameInit() {
snake.gamesizeheight = 6;
snake.gamesizewidth = 8;
snake.isGameOver = 0;
snake.Dir = RIGHT;
snake.x = 1; //snake.gamesizewidth / 2;
snake.y = 1; //snake.gamesizeheight / 2;
snake.fruitCordX = rand() % snake.gamesizewidth;
snake.fruitCordY = rand() % snake.gamesizeheight;
snake.playerScore = 0;
snake.TailLen = 0;
snake.TailGrowPending = 0;
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_FillScreen(WHITE);
osMutexRelease(displayHandle);
}
}
// Function for updating the game state
void UpdateGame() {
char dir;
// check the queue non blocking
osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL, 0); // 0 = no wait
if (status == osOK) {
switch (dir) {
case 'L':
snake.Dir = LEFT;
break;
case 'R':
snake.Dir = RIGHT;
break;
case 'U':
snake.Dir = UP;
break;
case 'D':
snake.Dir = DOWN;
break;
}
}
if (!snake.TailGrowPending) {
if (snake.TailLen > 0) {
snake.TailPendingDeletionX = snake.TailX[snake.TailLen - 1];
snake.TailPendingDeletionY = snake.TailY[snake.TailLen - 1];
} else {
snake.TailPendingDeletionX = snake.x;
snake.TailPendingDeletionY = snake.y;
}
}
snake.TailGrowPending = 0;
// tail movement
if (snake.TailLen > 0) {
for (int i = snake.TailLen - 1; i > 0; i--) {
snake.TailX[i] = snake.TailX[i - 1];
snake.TailY[i] = snake.TailY[i - 1];
}
snake.TailX[0] = snake.x;
snake.TailY[0] = snake.y;
}
switch (snake.Dir) {
case LEFT:
snake.x--;
break;
case RIGHT:
snake.x++;
break;
case UP:
snake.y--;
break;
case DOWN:
snake.y++;
break;
}
// Checks for snake's collision with the wall
if (snake.x >= snake.gamesizewidth || snake.x < 0
|| snake.y >= snake.gamesizeheight || snake.y < 0)
snake.isGameOver = 1;
// Checks for collision with the tail (o)
for (int i = 0; i < snake.TailLen; i++) {
if (snake.TailX[i] == snake.x && snake.TailY[i] == snake.y)
snake.isGameOver = 1;
}
// Checks for snake's collision with the food (#)
if (snake.x == snake.fruitCordX && snake.y == snake.fruitCordY) {
snake.playerScore += 10;
snake.fruitCordX = rand() % snake.gamesizewidth;
snake.fruitCordY = rand() % snake.gamesizeheight;
snake.TailLen++;
snake.TailX[snake.TailLen - 1] = snake.x;
snake.TailY[snake.TailLen - 1] = snake.y;
snake.TailGrowPending = 1;
//snake.TailPendingDeletionX = -1;
}
if (snake.isGameOver) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
if (Flash_Read_HighScore() > snake.playerScore) {
char str[50];
sprintf(str, "Highscore Remains: %lu", Flash_Read_HighScore());
ILI9341_DrawText(str, FONT3, 320 / 2 - 70, 240 / 2, BLACK,
WHITE);
// ILI9341_WriteString(320 / 2 - 70, 240 / 2, str, Font_11x18,
//ILI9341_MAGENTA, ILI9341_WHITE);
} else {
char str[50];
sprintf(str, "New Highscore: %lu", snake.playerScore);
//ILI9341_WriteString(320 / 2 - 70, 240 / 2, str, Font_11x18,
//ILI9341_MAGENTA, ILI9341_WHITE);
ILI9341_DrawText(str, FONT3, 320 / 2 - 70, 240 / 2, BLACK,
WHITE);
Flash_Write_HighScore(snake.playerScore);
}
osMutexRelease(displayHandle);
}
}
}
// Function for creating the game board & rendering
void GameRender() {
// Creating top walls
// Creating side walls
//ILI9341_FillRectangle(j, i, ILI9341_WIDTH/snake.gamesizewidth, ILI9341_HEIGHT/snake.gamesizeheight, ILI9341_YELLOW);
//ILI9341_FillScreen(MAGENTA);
for (int x = 0; x < snake.gamesizewidth; x++) {
for (int y = 0; y <= snake.gamesizeheight; y++) {
if (x == snake.x && y == snake.y) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
BLACK);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_BLACK);
osMutexRelease(displayHandle);
}
}
//cout << "O";
// Creating the sanke's food with '#'
else if (x == snake.fruitCordX && y == snake.fruitCordY) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
RED);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight, ILI9341_RED);
osMutexRelease(displayHandle);
}
}
//cout << "#";
else if (snake.TailLen >= 0) {
for (int i = 0; i < snake.TailLen; i++) {
if (snake.TailX[0] == x && snake.TailY[0] == y) {
if (osMutexAcquire(displayHandle, osWaitForever)
== osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH)
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT)
/ snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH)
/ snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT)
/ snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
GREEN);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_GREEN);
osMutexRelease(displayHandle);
}
}
}
}
if (snake.TailPendingDeletionX == x
&& snake.TailPendingDeletionY == y) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawFilledRectangleCoord(
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight,
(x * ILI9341_SCREEN_WIDTH) / snake.gamesizewidth
+ ILI9341_SCREEN_WIDTH
/ snake.gamesizewidth,
(y * ILI9341_SCREEN_HEIGHT) / snake.gamesizeheight
+ ILI9341_SCREEN_HEIGHT
/ snake.gamesizeheight,
WHITE);
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_WHITE);
osMutexRelease(displayHandle);
}
}
}
}
}
int isGameOver(){
return snake.isGameOver;
}

54
Core/Src/snake.h Normal file
View File

@ -0,0 +1,54 @@
/*
* snake.h
*
* Created on: Jul 10, 2025
* Author: user
*/
#ifndef SRC_SNAKE_H_
#define SRC_SNAKE_H_
#include "main.h"
extern osMutexId_t displayHandle;
extern osMessageQueueId_t pressesHandle;
// Flash storage address for highscore
#define FLASH_USER_ADDR ((uint32_t)0x0803F000) // Adjusted to your sector layout
// Highscore flash functions
void Flash_Write_HighScore(uint32_t highscore);
uint32_t Flash_Read_HighScore(void);
// Snake movement direction enum
enum Direction {
STOP = 0, LEFT, RIGHT, UP, DOWN
};
// Snake structure definition
struct Snake {
int x, y;
int fruitCordX, fruitCordY;
int playerScore;
int TailX[100], TailY[100];
int TailLen;
enum Direction Dir;
int gamesizewidth;
int gamesizeheight;
int TailPendingDeletionX;
int TailPendingDeletionY;
int TailGrowPending;
int isGameOver;
};
// External instance of the snake object
extern struct Snake snake;
// Game functions
void GameInit(void);
void UpdateGame(void);
void GameRender(void);
int isGameOver();
#endif /* SRC_SNAKE_H_ */

View File

@ -225,31 +225,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
/* USER CODE BEGIN SPI1_MspInit 1 */ /* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */ /* USER CODE END SPI1_MspInit 1 */
}
else if(hspi->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspInit 0 */
/* USER CODE END SPI2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**SPI2 GPIO Configuration
PB10 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_14|GPIO_PIN_15;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* USER CODE BEGIN SPI2_MspInit 1 */
/* USER CODE END SPI2_MspInit 1 */
} }
} }
@ -287,25 +263,6 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
/* USER CODE END SPI1_MspDeInit 1 */ /* USER CODE END SPI1_MspDeInit 1 */
} }
else if(hspi->Instance==SPI2)
{
/* USER CODE BEGIN SPI2_MspDeInit 0 */
/* USER CODE END SPI2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI2_CLK_DISABLE();
/**SPI2 GPIO Configuration
PB10 ------> SPI2_SCK
PB14 ------> SPI2_MISO
PB15 ------> SPI2_MOSI
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10|GPIO_PIN_14|GPIO_PIN_15);
/* USER CODE BEGIN SPI2_MspDeInit 1 */
/* USER CODE END SPI2_MspDeInit 1 */
}
} }
@ -519,6 +476,9 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
GPIO_InitStruct.Alternate = GPIO_AF8_USART6; GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART6 interrupt Init */
HAL_NVIC_SetPriority(USART6_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USART6_IRQn);
/* USER CODE BEGIN USART6_MspInit 1 */ /* USER CODE BEGIN USART6_MspInit 1 */
/* USER CODE END USART6_MspInit 1 */ /* USER CODE END USART6_MspInit 1 */
@ -549,6 +509,8 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
*/ */
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12); HAL_GPIO_DeInit(GPIOA, GPIO_PIN_11|GPIO_PIN_12);
/* USART6 interrupt DeInit */
HAL_NVIC_DisableIRQ(USART6_IRQn);
/* USER CODE BEGIN USART6_MspDeInit 1 */ /* USER CODE BEGIN USART6_MspDeInit 1 */
/* USER CODE END USART6_MspDeInit 1 */ /* USER CODE END USART6_MspDeInit 1 */

View File

@ -1,20 +1,20 @@
/* USER CODE BEGIN Header */ /* USER CODE BEGIN Header */
/** /**
****************************************************************************** ******************************************************************************
* @file stm32f4xx_it.c * @file stm32f4xx_it.c
* @brief Interrupt Service Routines. * @brief Interrupt Service Routines.
****************************************************************************** ******************************************************************************
* @attention * @attention
* *
* Copyright (c) 2025 STMicroelectronics. * Copyright (c) 2025 STMicroelectronics.
* All rights reserved. * All rights reserved.
* *
* This software is licensed under terms that can be found in the LICENSE file * This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component. * in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS. * If no LICENSE file comes with this software, it is provided AS-IS.
* *
****************************************************************************** ******************************************************************************
*/ */
/* USER CODE END Header */ /* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/
@ -58,6 +58,7 @@
extern DMA_HandleTypeDef hdma_spi1_rx; extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx; extern DMA_HandleTypeDef hdma_spi1_tx;
extern SPI_HandleTypeDef hspi1; extern SPI_HandleTypeDef hspi1;
extern UART_HandleTypeDef huart6;
extern TIM_HandleTypeDef htim2; extern TIM_HandleTypeDef htim2;
/* USER CODE BEGIN EV */ /* USER CODE BEGIN EV */
@ -76,9 +77,8 @@ void NMI_Handler(void)
/* USER CODE END NonMaskableInt_IRQn 0 */ /* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */ /* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1) while (1) {
{ }
}
/* USER CODE END NonMaskableInt_IRQn 1 */ /* USER CODE END NonMaskableInt_IRQn 1 */
} }
@ -218,6 +218,20 @@ void DMA2_Stream3_IRQHandler(void)
/* USER CODE END DMA2_Stream3_IRQn 1 */ /* USER CODE END DMA2_Stream3_IRQn 1 */
} }
/**
* @brief This function handles USART6 global interrupt.
*/
void USART6_IRQHandler(void)
{
/* USER CODE BEGIN USART6_IRQn 0 */
/* USER CODE END USART6_IRQn 0 */
HAL_UART_IRQHandler(&huart6);
/* USER CODE BEGIN USART6_IRQn 1 */
UART_CALLBACK();
/* USER CODE END USART6_IRQn 1 */
}
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
/* USER CODE END 1 */ /* USER CODE END 1 */

View File

@ -29,7 +29,7 @@ FREERTOS.FootprintOK=true
FREERTOS.IPParameters=Tasks01,FootprintOK,configUSE_NEWLIB_REENTRANT,Queues01,Mutexes01,configGENERATE_RUN_TIME_STATS,configUSE_STATS_FORMATTING_FUNCTIONS FREERTOS.IPParameters=Tasks01,FootprintOK,configUSE_NEWLIB_REENTRANT,Queues01,Mutexes01,configGENERATE_RUN_TIME_STATS,configUSE_STATS_FORMATTING_FUNCTIONS
FREERTOS.Mutexes01=display,Dynamic,NULL,Available FREERTOS.Mutexes01=display,Dynamic,NULL,Available
FREERTOS.Queues01=presses,16,char,0,Dynamic,NULL,NULL FREERTOS.Queues01=presses,16,char,0,Dynamic,NULL,NULL
FREERTOS.Tasks01=touchhistory,24,128,StartTouchHist,Default,NULL,Dynamic,NULL,NULL;draw,8,128,snakegame,Default,NULL,Dynamic,NULL,NULL;reactiongame,8,128,startreactiongame,Default,NULL,Dynamic,NULL,NULL;gamepicker,8,128,gamepicker_entry,Default,NULL,Dynamic,NULL,NULL FREERTOS.Tasks01=touchhistory,24,128,StartTouchHist,Default,NULL,Dynamic,NULL,NULL;draw,8,512,snakegame,Default,NULL,Dynamic,NULL,NULL;menu,8,256,handle_menu,Default,NULL,Dynamic,NULL,NULL
FREERTOS.configGENERATE_RUN_TIME_STATS=1 FREERTOS.configGENERATE_RUN_TIME_STATS=1
FREERTOS.configUSE_NEWLIB_REENTRANT=1 FREERTOS.configUSE_NEWLIB_REENTRANT=1
FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1 FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1
@ -40,52 +40,46 @@ Mcu.CPN=STM32F401CCU6
Mcu.Family=STM32F4 Mcu.Family=STM32F4
Mcu.IP0=DMA Mcu.IP0=DMA
Mcu.IP1=FREERTOS Mcu.IP1=FREERTOS
Mcu.IP10=TIM5 Mcu.IP10=USART6
Mcu.IP11=USART6
Mcu.IP2=I2C1 Mcu.IP2=I2C1
Mcu.IP3=NVIC Mcu.IP3=NVIC
Mcu.IP4=RCC Mcu.IP4=RCC
Mcu.IP5=SPI1 Mcu.IP5=SPI1
Mcu.IP6=SPI2 Mcu.IP6=SYS
Mcu.IP7=SYS Mcu.IP7=TIM1
Mcu.IP8=TIM1 Mcu.IP8=TIM4
Mcu.IP9=TIM4 Mcu.IP9=TIM5
Mcu.IPNb=12 Mcu.IPNb=11
Mcu.Name=STM32F401C(B-C)Ux Mcu.Name=STM32F401C(B-C)Ux
Mcu.Package=UFQFPN48 Mcu.Package=UFQFPN48
Mcu.Pin0=PC13-ANTI_TAMP Mcu.Pin0=PC13-ANTI_TAMP
Mcu.Pin1=PA0-WKUP Mcu.Pin1=PA0-WKUP
Mcu.Pin10=PB2 Mcu.Pin10=PA8
Mcu.Pin11=PB10 Mcu.Pin11=PA9
Mcu.Pin12=PB14 Mcu.Pin12=PA10
Mcu.Pin13=PB15 Mcu.Pin13=PA11
Mcu.Pin14=PA8 Mcu.Pin14=PA12
Mcu.Pin15=PA9 Mcu.Pin15=PA13
Mcu.Pin16=PA10 Mcu.Pin16=PA14
Mcu.Pin17=PA11 Mcu.Pin17=PA15
Mcu.Pin18=PA12 Mcu.Pin18=PB3
Mcu.Pin19=PA13 Mcu.Pin19=PB4
Mcu.Pin2=PA1 Mcu.Pin2=PA1
Mcu.Pin20=PA14 Mcu.Pin20=PB6
Mcu.Pin21=PA15 Mcu.Pin21=PB7
Mcu.Pin22=PB3 Mcu.Pin22=PB8
Mcu.Pin23=PB4 Mcu.Pin23=PB9
Mcu.Pin24=PB5 Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V2
Mcu.Pin25=PB6 Mcu.Pin25=VP_SYS_VS_tim2
Mcu.Pin26=PB7 Mcu.Pin26=VP_TIM5_VS_ClockSourceINT
Mcu.Pin27=PB8
Mcu.Pin28=PB9
Mcu.Pin29=VP_FREERTOS_VS_CMSIS_V2
Mcu.Pin3=PA2 Mcu.Pin3=PA2
Mcu.Pin30=VP_SYS_VS_tim2
Mcu.Pin31=VP_TIM5_VS_ClockSourceINT
Mcu.Pin4=PA3 Mcu.Pin4=PA3
Mcu.Pin5=PA4 Mcu.Pin5=PA4
Mcu.Pin6=PA5 Mcu.Pin6=PA5
Mcu.Pin7=PA6 Mcu.Pin7=PA6
Mcu.Pin8=PA7 Mcu.Pin8=PA7
Mcu.Pin9=PB1 Mcu.Pin9=PB2
Mcu.PinsNb=32 Mcu.PinsNb=27
Mcu.ThirdPartyNb=0 Mcu.ThirdPartyNb=0
Mcu.UserConstants= Mcu.UserConstants=
Mcu.UserName=STM32F401CCUx Mcu.UserName=STM32F401CCUx
@ -110,6 +104,7 @@ NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
NVIC.TIM2_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true NVIC.TIM2_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
NVIC.TimeBase=TIM2_IRQn NVIC.TimeBase=TIM2_IRQn
NVIC.TimeBaseIP=TIM2 NVIC.TimeBaseIP=TIM2
NVIC.USART6_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
PA0-WKUP.Signal=S_TIM5_CH1 PA0-WKUP.Signal=S_TIM5_CH1
PA1.Signal=S_TIM5_CH2 PA1.Signal=S_TIM5_CH2
@ -144,16 +139,6 @@ PA7.Mode=Full_Duplex_Master
PA7.Signal=SPI1_MOSI PA7.Signal=SPI1_MOSI
PA8.Signal=S_TIM1_CH1 PA8.Signal=S_TIM1_CH1
PA9.Signal=S_TIM1_CH2 PA9.Signal=S_TIM1_CH2
PB1.GPIOParameters=GPIO_Label
PB1.GPIO_Label=TOUCH_CS
PB1.Locked=true
PB1.Signal=GPIO_Output
PB10.Mode=Full_Duplex_Master
PB10.Signal=SPI2_SCK
PB14.Mode=Full_Duplex_Master
PB14.Signal=SPI2_MISO
PB15.Mode=Full_Duplex_Master
PB15.Signal=SPI2_MOSI
PB2.GPIOParameters=GPIO_Label PB2.GPIOParameters=GPIO_Label
PB2.GPIO_Label=DISPLAY_DC PB2.GPIO_Label=DISPLAY_DC
PB2.Locked=true PB2.Locked=true
@ -164,10 +149,6 @@ PB3.Signal=SYS_JTDO-SWO
PB4.Locked=true PB4.Locked=true
PB4.Mode=JTAG_5_pins PB4.Mode=JTAG_5_pins
PB4.Signal=SYS_JTRST PB4.Signal=SYS_JTRST
PB5.GPIOParameters=GPIO_Label
PB5.GPIO_Label=TOUCH_IRQ
PB5.Locked=true
PB5.Signal=GPIO_Input
PB6.Signal=S_TIM4_CH1 PB6.Signal=S_TIM4_CH1
PB7.Signal=S_TIM4_CH2 PB7.Signal=S_TIM4_CH2
PB8.Mode=I2C PB8.Mode=I2C
@ -210,7 +191,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath= ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath= ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=true ProjectManager.UnderRoot=true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_TIM1_Init-TIM1-false-HAL-true,7-MX_TIM4_Init-TIM4-false-HAL-true,8-MX_TIM5_Init-TIM5-false-HAL-true,9-MX_USART6_UART_Init-USART6-false-HAL-true,10-MX_I2C1_Init-I2C1-false-HAL-true ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-HAL-false,2-MX_GPIO_Init-GPIO-false-HAL-true,3-MX_DMA_Init-DMA-false-HAL-true,4-MX_SPI1_Init-SPI1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,5-MX_TIM1_Init-TIM1-false-HAL-true,6-MX_TIM4_Init-TIM4-false-HAL-true,7-MX_TIM5_Init-TIM5-false-HAL-true,8-MX_USART6_UART_Init-USART6-false-HAL-true,9-MX_I2C1_Init-I2C1-false-HAL-true
RCC.AHBFreq_Value=16000000 RCC.AHBFreq_Value=16000000
RCC.APB1Freq_Value=16000000 RCC.APB1Freq_Value=16000000
RCC.APB2Freq_Value=16000000 RCC.APB2Freq_Value=16000000
@ -252,12 +233,6 @@ SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler
SPI1.Mode=SPI_MODE_MASTER SPI1.Mode=SPI_MODE_MASTER
SPI1.VirtualType=VM_MASTER SPI1.VirtualType=VM_MASTER
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_32
SPI2.CalculateBaudRate=500.0 KBits/s
SPI2.Direction=SPI_DIRECTION_2LINES
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler
SPI2.Mode=SPI_MODE_MASTER
SPI2.VirtualType=VM_MASTER
TIM1.EncoderMode=TIM_ENCODERMODE_TI12 TIM1.EncoderMode=TIM_ENCODERMODE_TI12
TIM1.IPParameters=EncoderMode TIM1.IPParameters=EncoderMode
TIM4.EncoderMode=TIM_ENCODERMODE_TI12 TIM4.EncoderMode=TIM_ENCODERMODE_TI12