Compare commits

..

No commits in common. "80086edc130f716682598c8e24e829dc8ed27486" and "cc57c38cc193063b204ba4682d7ca19806b8420b" have entirely different histories.

13 changed files with 694 additions and 906 deletions

View File

@ -51,10 +51,6 @@
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#include <stdint.h>
extern uint32_t SystemCoreClock;
/* USER CODE BEGIN 0 */
extern void configureTimerForRunTimeStats(void);
extern unsigned long getRunTimeCounterValue(void);
/* USER CODE END 0 */
#endif
#ifndef CMSIS_device_header
#define CMSIS_device_header "stm32f4xx.h"
@ -74,9 +70,7 @@
#define configMINIMAL_STACK_SIZE ((uint16_t)128)
#define configTOTAL_HEAP_SIZE ((size_t)15360)
#define configMAX_TASK_NAME_LEN ( 16 )
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1
#define configUSE_16_BIT_TICKS 0
#define configUSE_MUTEXES 1
#define configQUEUE_REGISTRY_SIZE 8
@ -172,12 +166,6 @@ standard names. */
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 0
/* USER CODE BEGIN 2 */
/* Definitions needed when configGENERATE_RUN_TIME_STATS is on */
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS configureTimerForRunTimeStats
#define portGET_RUN_TIME_COUNTER_VALUE getRunTimeCounterValue
/* USER CODE END 2 */
/* USER CODE BEGIN Defines */
/* Section where parameter definitions can be added (for instance, to override default ones in FreeRTOS.h) */
/* USER CODE END Defines */

View File

@ -59,14 +59,18 @@ void Error_Handler(void);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define LED_BLUE_Pin GPIO_PIN_13
#define LED_BLUE_GPIO_Port GPIOC
#define LED_Pin GPIO_PIN_13
#define LED_GPIO_Port GPIOC
#define DISPLAY_CS_Pin GPIO_PIN_4
#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_GPIO_Port GPIOB
#define DISPLAY_RES_Pin GPIO_PIN_10
#define DISPLAY_RES_GPIO_Port GPIOA
#define TOUCH_IRQ_Pin GPIO_PIN_5
#define TOUCH_IRQ_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */

View File

@ -52,11 +52,10 @@ void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void DebugMon_Handler(void);
void TIM3_IRQHandler(void);
void TIM2_IRQHandler(void);
void SPI1_IRQHandler(void);
void DMA2_Stream0_IRQHandler(void);
void DMA2_Stream3_IRQHandler(void);
void USART6_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

View File

@ -52,27 +52,6 @@
/* USER CODE END FunctionPrototypes */
/* Hook prototypes */
void configureTimerForRunTimeStats(void);
unsigned long getRunTimeCounterValue(void);
/* USER CODE BEGIN 1 */
/* Functions needed when configGENERATE_RUN_TIME_STATS is on */
__weak void configureTimerForRunTimeStats(void) {
// Configure TIM2 as a free-running timer at 1 MHz
__HAL_RCC_TIM2_CLK_ENABLE();
TIM2->PSC = (SystemCoreClock / 1000000) - 1; // 1 MHz
TIM2->ARR = 0xFFFFFFFF;
TIM2->CNT = 0;
TIM2->CR1 = TIM_CR1_CEN;
}
__weak unsigned long getRunTimeCounterValue(void) {
return TIM2->CNT;
return 0;
}
/* USER CODE END 1 */
/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

View File

@ -23,9 +23,10 @@
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
//#include "ili9341.h"
//#include "ili9341_touch.h"
#include "ILI9341_STM32_Driver.h"
#include "ILI9341_GFX.h"
#include "snake.h"
/* USER CODE END Includes */
@ -48,6 +49,7 @@
I2C_HandleTypeDef hi2c1;
SPI_HandleTypeDef hspi1;
SPI_HandleTypeDef hspi2;
DMA_HandleTypeDef hdma_spi1_rx;
DMA_HandleTypeDef hdma_spi1_tx;
@ -68,14 +70,21 @@ const osThreadAttr_t touchhistory_attributes = {
osThreadId_t drawHandle;
const osThreadAttr_t draw_attributes = {
.name = "draw",
.stack_size = 512 * 4,
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityLow,
};
/* Definitions for menu */
osThreadId_t menuHandle;
const osThreadAttr_t menu_attributes = {
.name = "menu",
.stack_size = 256 * 4,
/* Definitions for reactiongame */
osThreadId_t reactiongameHandle;
const osThreadAttr_t reactiongame_attributes = {
.name = "reactiongame",
.stack_size = 128 * 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,
};
/* Definitions for presses */
@ -97,6 +106,7 @@ void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_SPI1_Init(void);
static void MX_SPI2_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM4_Init(void);
static void MX_TIM5_Init(void);
@ -104,7 +114,8 @@ static void MX_USART6_UART_Init(void);
static void MX_I2C1_Init(void);
void StartTouchHist(void *argument);
void snakegame(void *argument);
void handle_menu(void *argument);
void startreactiongame(void *argument);
void gamepicker_entry(void *argument);
/* USER CODE BEGIN PFP */
@ -112,84 +123,304 @@ void handle_menu(void *argument);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
int run_snake = 0;
int run_menu = 1;
#define RX_BUFFER_SIZE 1
#define LINE_BUFFER_SIZE 128
#define touchbuffersize 50
struct {
int x[touchbuffersize];
int y[touchbuffersize];
} touchcoord;
uint8_t rx_buffer[RX_BUFFER_SIZE];
char line_buffer[LINE_BUFFER_SIZE];
uint16_t line_pos = 0;
void titlescreen() {
ILI9341_FillScreen(WHITE);
char str[50];
sprintf(str, "snake");
ILI9341_DrawText(str, FONT3, 320 / 2 - 100, 240 / 2, BLACK, WHITE);
//menu
int redraw_menu_pending;
#define GRID_X 2
#define GRID_Y 3
uint8_t menu_status[GRID_X][GRID_Y] = { 0 };
void process_line(const char *line) {
if (strncmp(line, "ABS:", 4) == 0) {
char axis[32];
int value;
if (sscanf(line, "ABS:%31[^:]:%d:", axis, &value) == 2) {
// Handle axis input
if (strcmp(axis, "ABS_X") == 0) {
// Do something with X axis
} else if (strcmp(axis, "ABS_Y") == 0) {
// Do something with Y axis
sprintf(str, "1v1");
ILI9341_DrawText(str, FONT3, 10, 30, BLACK, WHITE);
//ILI9341_WriteString(320 / 2 + 100, 240 / 2, str, Font_11x18,
//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;
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;
}
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;
// Game over flag
int isGameOver;
} snake;
// Function to initialize game variables
void GameInit() {
snake.gamesizeheight = 6;
snake.gamesizewidth = 8;
snake.isGameOver = 0;
snake.Dir = STOP;
snake.x = snake.gamesizewidth / 2;
snake.y = snake.gamesizeheight / 2;
snake.fruitCordX = rand() % snake.gamesizewidth;
snake.fruitCordY = rand() % snake.gamesizeheight;
snake.playerScore = 0;
snake.TailLen = 0;
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
//ILI9341_FillScreen(ILI9341_WHITE);
osMutexRelease(displayHandle);
}
}
} 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
// Function for updating the game state
void UpdateGame() {
int prevX = snake.TailX[0];
int prevY = snake.TailY[0];
int prev2X, prev2Y;
snake.TailX[0] = snake.x;
snake.TailY[0] = snake.y;
snake.TailPendingDeletionX = snake.TailX[snake.TailLen];
snake.TailPendingDeletionY = snake.TailY[snake.TailLen];
for (int i = 1; i < snake.TailLen; i++) {
prev2X = snake.TailX[i];
prev2Y = snake.TailY[i];
snake.TailX[i] = prevX;
snake.TailY[i] = prevY;
prevX = prev2X;
prevY = prev2Y;
}
//we only care about presses
if (state) {
char dir;
dir = key[0];
osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0,
0);
// 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;
}
}
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++;
}
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_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);
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;
//if (ILI9341_TouchGetCoordinates(&x, &y)) { // Only act if touch detected
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
}
// Send the direction to the queue
//if (!prevpressed && ILI9341_TouchPressed()) {
osStatus_t status = osMessageQueuePut(pressesHandle, &dir, 0, 0);
if (status != osOK) {
// Optional: Handle error
}
//}
prevpressed = 1;
//} else {
prevpressed = 0;
//give illegal coords
//if it is already we can skip it
//if (touchcoord.x[0] != ILI9341_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];
}
if (key[0] == 'B' && state == 1) { // B goes to the menu
run_snake = 0;
run_menu = 1;
redraw_menu_pending = 1;
}
if (key[0] == 'Y' && state == 1) { // Y reboot
// touchcoord.x[touchbuffersize - 1] = ILI9341_WIDTH;
// touchcoord.y[touchbuffersize - 1] = ILI9341_HEIGHT;
//}
//}
}
}
}
}
void UART_CALLBACK() {
char ch = rx_buffer[0];
// Function for creating the game board & rendering
void GameRender() {
if (ch == '\r') {
// ignore
} else if (ch == '\n') {
//line_buffer[line_pos] = '\0';
if (line_buffer[1] == 'K' || line_buffer[1] == 'A') {
process_line(&line_buffer[1]);
} else {
process_line(line_buffer);
// Creating top walls
// Creating side walls
//ILI9341_FillRectangle(j, i, ILI9341_WIDTH/snake.gamesizewidth, ILI9341_HEIGHT/snake.gamesizeheight, ILI9341_YELLOW);
ILI9341_FillScreen(WHITE);
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_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_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight, ILI9341_RED);
osMutexRelease(displayHandle);
}
}
//cout << "#";
// Creating snake's head with 'O'
else if (snake.TailX[0] == x && snake.TailY[0] == y) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// ILI9341_FillRectangle(
// (x * ILI9341_WIDTH) / snake.gamesizewidth,
// (y * ILI9341_HEIGHT) / snake.gamesizeheight,
// ILI9341_WIDTH / snake.gamesizewidth,
// ILI9341_HEIGHT / snake.gamesizeheight,
// ILI9341_GREEN);
osMutexRelease(displayHandle);
}
} else if (snake.TailPendingDeletionX == x
&& snake.TailPendingDeletionY == y) {
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
// 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 */
@ -212,6 +443,7 @@ int main(void)
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
@ -225,24 +457,22 @@ int main(void)
MX_GPIO_Init();
MX_DMA_Init();
MX_SPI1_Init();
MX_SPI2_Init();
MX_TIM1_Init();
MX_TIM4_Init();
MX_TIM5_Init();
MX_USART6_UART_Init();
MX_I2C1_Init();
/* USER CODE BEGIN 2 */
ILI9341_Init();
ILI9341_SetRotation(SCREEN_HORIZONTAL_1);
//ILI9341_FillScreen(WHITE);
//void XPT2046_Init();
//Flash_Write_HighScore(100);
//ILI9341_FillRectangle(100, 100, 100, 100, ILI9341_GREEN);
/* USER CODE END 2 */
/* Init scheduler */
osKernelInitialize();
//osKernelInitialize();
/* Create the mutex(es) */
/* creation of display */
displayHandle = osMutexNew(&display_attributes);
//displayHandle = osMutexNew(&display_attributes);
/* USER CODE BEGIN RTOS_MUTEX */
/* add mutexes, ... */
@ -258,7 +488,7 @@ int main(void)
/* Create the queue(s) */
/* creation of presses */
pressesHandle = osMessageQueueNew (16, sizeof(char), &presses_attributes);
//pressesHandle = osMessageQueueNew (16, sizeof(char), &presses_attributes);
/* USER CODE BEGIN RTOS_QUEUES */
/* add queues, ... */
@ -266,13 +496,16 @@ int main(void)
/* Create the thread(s) */
/* creation of touchhistory */
touchhistoryHandle = osThreadNew(StartTouchHist, NULL, &touchhistory_attributes);
//touchhistoryHandle = osThreadNew(StartTouchHist, NULL, &touchhistory_attributes);
/* creation of draw */
drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
//drawHandle = osThreadNew(snakegame, NULL, &draw_attributes);
/* creation of menu */
menuHandle = osThreadNew(handle_menu, NULL, &menu_attributes);
/* creation of reactiongame */
//reactiongameHandle = osThreadNew(startreactiongame, NULL, &reactiongame_attributes);
/* creation of gamepicker */
//gamepickerHandle = osThreadNew(gamepicker_entry, NULL, &gamepicker_attributes);
/* USER CODE BEGIN RTOS_THREADS */
/* add threads, ... */
@ -293,21 +526,21 @@ int main(void)
/* USER CODE END RTOS_EVENTS */
/* Start scheduler */
osKernelStart();
//osKernelStart();
/* We should never get here as control is now taken by the scheduler */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
//int a[4] = { ILI9341_GREEN, ILI9341_WHITE, ILI9341_BLACK, ILI9341_BLUE };
int cnt;
while (hspi1.State != HAL_SPI_STATE_READY)
;
while (hspi1.State != HAL_SPI_STATE_READY);
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
;
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY);
ILI9341_Init();
ILI9341_SetRotation(SCREEN_HORIZONTAL_1);
while (1) {
@ -320,15 +553,14 @@ int main(void)
//ILI9341_FillScreen(MAGENTA);
//ILI9341_DrawFilledRectangleCoord(10, 10, 20, 20, RED);
//ILI9341_FillScreen(WHITE);
HAL_Delay(1);
char str[20];
sprintf(str, "%lu", cnt % 1000);
int atim = HAL_GetTick();
//ILI9341_DrawFilledRectangleCoord(10, 10, 20, 20, GREEN);
//ILI9341_FillScreen(MAGENTA);
//ILI9341_FillScreen(atim%0xFFFF);
ILI9341_FillScreen(atim%0xFFFF);
//ILI9341_DrawText(str, FONT4, 50, 50, WHITE, BLACK);
//ILI9341_DrawChar('C', FONT4, 40, 40, WHITE, BLACK);
int c = HAL_GetTick() - atim;
@ -455,6 +687,44 @@ 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_32;
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
* @param None
@ -483,12 +753,12 @@ static void MX_TIM1_Init(void)
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV8;
sConfig.IC1Filter = 15;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV8;
sConfig.IC2Filter = 15;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim1, &sConfig) != HAL_OK)
{
Error_Handler();
@ -532,12 +802,12 @@ static void MX_TIM4_Init(void)
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV8;
sConfig.IC1Filter = 15;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV8;
sConfig.IC2Filter = 15;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0;
if (HAL_TIM_Encoder_Init(&htim4, &sConfig) != HAL_OK)
{
Error_Handler();
@ -566,6 +836,7 @@ static void MX_TIM5_Init(void)
/* USER CODE END TIM5_Init 0 */
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
@ -573,11 +844,20 @@ static void MX_TIM5_Init(void)
/* USER CODE END TIM5_Init 1 */
htim5.Instance = TIM5;
htim5.Init.Prescaler = 92;
htim5.Init.Prescaler = 0;
htim5.Init.CounterMode = TIM_COUNTERMODE_UP;
htim5.Init.Period = 10000;
htim5.Init.Period = 4294967295;
htim5.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim5.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim5) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim5, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim5) != HAL_OK)
{
Error_Handler();
@ -643,8 +923,6 @@ static void MX_USART6_UART_Init(void)
Error_Handler();
}
/* USER CODE BEGIN USART6_Init 2 */
uint8_t rx_byte;
HAL_UART_Receive_IT(&huart6, &rx_byte, 1);
/* USER CODE END USART6_Init 2 */
@ -687,20 +965,20 @@ static void MX_GPIO_Init(void)
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(LED_BLUE_GPIO_Port, LED_BLUE_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, DISPLAY_CS_Pin|DISPLAY_RES_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(DISPLAY_DC_GPIO_Port, DISPLAY_DC_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, TOUCH_CS_Pin|DISPLAY_DC_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin : LED_BLUE_Pin */
GPIO_InitStruct.Pin = LED_BLUE_Pin;
/*Configure GPIO pin : LED_Pin */
GPIO_InitStruct.Pin = LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(LED_BLUE_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(LED_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : DISPLAY_CS_Pin DISPLAY_RES_Pin */
GPIO_InitStruct.Pin = DISPLAY_CS_Pin|DISPLAY_RES_Pin;
@ -709,12 +987,18 @@ static void MX_GPIO_Init(void)
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin : DISPLAY_DC_Pin */
GPIO_InitStruct.Pin = DISPLAY_DC_Pin;
/*Configure GPIO pins : TOUCH_CS_Pin DISPLAY_DC_Pin */
GPIO_InitStruct.Pin = TOUCH_CS_Pin|DISPLAY_DC_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(DISPLAY_DC_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_Init(GPIOB, &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 */
@ -737,6 +1021,15 @@ 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], ILI9341_MAGENTA);
// ILI9341_DrawPixel(touchcoord.x[0], touchcoord.y[0], ILI9341_WHITE);
osMutexRelease(displayHandle);
}
osDelay(1);
}
/* USER CODE END 5 */
@ -753,167 +1046,127 @@ void snakegame(void *argument)
{
/* USER CODE BEGIN snakegame */
/* Infinite loop */
//ILI9341_FillScreen(BLACK);
GameInit();
for (;;) {
if (run_snake) {
GameRender();
static char statsBuffer[200];
vTaskGetRunTimeStats(statsBuffer);
vTaskDelay(300);
if (isGameOver()) {
vTaskDelay(2000);
GameInit();
}
osDelay(200);
UpdateGame();
} else {
vTaskDelay(10);
GameRender();
}
}
/* USER CODE END snakegame */
}
/* USER CODE BEGIN Header_handle_menu */
/* USER CODE BEGIN Header_startreactiongame */
/**
* @brief Function implementing the menu thread.
* @brief Function implementing the reactiongame thread.
* @param argument: Not used
* @retval None
*/
#define CELL_WIDTH 120 // Adjust as needed for your screen
#define CELL_HEIGHT 40
#define START_X 10
#define START_Y 10
#define COLOR_TEXT BLACK
#define COLOR_BG WHITE
#define COLOR_SELECTED GREEN
#define COLOR_ACTIVATED RED
#define COLOR_ACTIVATED_AND_SELECTED MAGENTA
int sel_x;
int sel_y;
//redraw_menu_pending is for redrawing
// Customize grid labels as needed
const char *grid_labels[GRID_X][GRID_Y] = { { "Snake", "Options", "About" }, {
"Highscore", "Credits", "Exit" } };
void redraw_menu() { //only done onece saves resources
// Redraw grid
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_FillScreen(WHITE);
osMutexRelease(displayHandle);
}
for (int i = 0; i < GRID_X; i++) {
for (int j = 0; j < GRID_Y; j++) {
uint16_t x = START_X + i * CELL_WIDTH;
uint16_t y = START_Y + j * CELL_HEIGHT;
uint16_t bg;
if (menu_status[i][j]) {
if (i == sel_x && j == sel_y) {
bg = COLOR_ACTIVATED_AND_SELECTED;
} else {
bg = COLOR_ACTIVATED;
}
} else {
if (i == sel_x && j == sel_y) {
bg = COLOR_SELECTED;
} else {
bg = COLOR_BG;
}
}
if (osMutexAcquire(displayHandle, osWaitForever) == osOK) {
ILI9341_DrawText(grid_labels[i][j], FONT2, x, y, COLOR_TEXT,
bg);
osMutexRelease(displayHandle);
}
}
}
}
/* USER CODE END Header_handle_menu */
void handle_menu(void *argument)
/* USER CODE END Header_startreactiongame */
void startreactiongame(void *argument)
{
/* USER CODE BEGIN handle_menu */
/* USER CODE BEGIN startreactiongame */
/* Infinite loop */
uint32_t lasttimestamp = osKernelGetTickCount();
for (;;) {
int a = rand() % 4000;
osDelay(1000 + a);
char dir;
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;
vTaskDelay(50);
redraw_menu();
while (1) {
// Check input
if (run_menu) {
// Wait for input (blocking)
osStatus_t status = osMessageQueueGet(pressesHandle, &dir, NULL,
osWaitForever);
if (status == osOK) {
//what was selected?
if (dir == 'A') {
if (grid_labels[sel_x][sel_y] == "Snake") {
run_snake = 1;
run_menu = 0;
}
menu_status[sel_x][sel_y] = !menu_status[sel_x][sel_y];
}
if (dir == 'U' || dir == 'D' || dir == 'L' || dir == 'R') {
if (menu_status[sel_x][sel_y]) {
ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2,
START_X + sel_x * CELL_WIDTH,
START_Y + sel_y * CELL_HEIGHT, COLOR_TEXT,
COLOR_ACTIVATED);
} else {
ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2,
START_X + sel_x * CELL_WIDTH,
START_Y + sel_y * CELL_HEIGHT, COLOR_TEXT,
COLOR_BG);
}
}
if (dir == 'U' && sel_y > 0)
sel_y--;
else if (dir == 'D' && sel_y < GRID_Y - 1)
sel_y++;
else if (dir == 'L' && sel_x > 0)
sel_x--;
else if (dir == 'R' && sel_x < GRID_X - 1)
sel_x++;
}
if (menu_status[sel_x][sel_y]) {
ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2,
START_X + sel_x * CELL_WIDTH, START_Y + sel_y * CELL_HEIGHT,
COLOR_TEXT,
COLOR_ACTIVATED_AND_SELECTED);
} else {
ILI9341_DrawText(grid_labels[sel_x][sel_y], FONT2,
START_X + sel_x * CELL_WIDTH, START_Y + sel_y * CELL_HEIGHT,
COLOR_TEXT,
COLOR_SELECTED);
}
if (redraw_menu_pending) {
redraw_menu();
redraw_menu_pending = 0;
}
}
osDelay(10);
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 handle_menu */
}
}
/* USER CODE END gamepicker_entry */
}
/**
* @brief Period elapsed callback in non blocking mode
* @note This function is called when TIM3 interrupt took place, inside
* @note This function is called when TIM2 interrupt took place, inside
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
* a global variable "uwTick" used as application time base.
* @param htim : TIM handle
@ -924,7 +1177,7 @@ void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
/* USER CODE BEGIN Callback 0 */
/* USER CODE END Callback 0 */
if (htim->Instance == TIM3)
if (htim->Instance == TIM2)
{
HAL_IncTick();
}

View File

@ -1,92 +0,0 @@
#!/usr/bin/env python3
import evdev
from evdev import InputDevice, categorize, ecodes
import glob
import serial
import time
# Controller
#device_candidates = glob.glob('/dev/input/by-id/usb-8BitDo*-event*')
device_candidates = glob.glob('/dev/input/by-id/usb-8Bit*')
if not device_candidates:
print("Error: No matching 8BitDo input device found.")
sys.exit(1)
device_path = device_candidates[0]
#device_path = '/dev/input/by-id/usb-8BitDo_8BitDo_Ultimate_Controller_6fdf5bd817e4-event-joystick' #or just put it in
# UART
serial_port = '/dev/ttyUSB0'
baudrate = 115200
device = InputDevice(device_path)
print(f"Listening on {device.name} ({device_path})")
ser = serial.Serial(serial_port, baudrate, timeout=1)
print(f"UART opened on {serial_port} at {baudrate} bps")
# diganostic time stamps
def timestamp_ms():
return int(time.time() * 1000)
import select
button_map = {
'BTN_SOUTH': 'B',
'BTN_EAST': 'A',
'BTN_NORTH': 'Y',
'BTN_WEST': 'X',
}
try:
while True:
r, w, x = select.select([device.fd], [], [], 0.005) # timeout = 10ms
if device.fd in r:
for event in device.read():
ts = timestamp_ms()
if event.type == ecodes.EV_KEY:
key_event = categorize(event)
k = key_event.keycode
if isinstance(k, tuple):
name = next((button_map[x] for x in k if x in button_map), str(k))
else:
name = button_map.get(k, k)
msg = f"KEY:{name}:{key_event.keystate}\n"
ser.write(msg.encode('utf-8'))
print(f"[{ts}] Sent: {msg.strip()}")
elif event.type == ecodes.EV_ABS:
axis = ecodes.ABS.get(event.code, f"ABS_{event.code}")
val = event.value
if axis == 'ABS_HAT0Y' or axis == 'ABS_HAT0X':
if axis == 'ABS_HAT0Y':
if val == -1:
ser.write(b"KEY:U:1\r\n")
print(f"[{ts}] Sent: KEY:U:1:")
elif val == 1:
ser.write(b"KEY:D:1\r\n")
print(f"[{ts}] Sent: KEY:D:1:")
elif val == 0:
#ser.write(b"KEY:U:0\r\nKEY:D:0\r\n")
print(f"[{ts}] Sent: KEY:U:0\n[{ts}] Sent: KEY:D:0")
elif axis == 'ABS_HAT0X':
if val == -1:
ser.write(b"KEY:L:1\r\n")
print(f"[{ts}] Sent: KEY:L:1:")
elif val == 1:
ser.write(b"KEY:R:1\r\n")
print(f"[{ts}] Sent: KEY:R:1:")
elif val == 0:
#ser.write(b"KEY:L:0\r\nKEY:R:0\r\n")
print(f"[{ts}] Sent: KEY:L:0\n[{ts}] Sent: KEY:R:0")
else:
msg = f"ABS:{axis}:{event.value}:\r\n"
ser.write(msg.encode('utf-8'))
print(f"[{ts}] Sent: {msg.strip()}")
except KeyboardInterrupt:
print("\nExiting...")
finally:
ser.close()
print("UART closed.")

View File

@ -1,285 +0,0 @@
#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;
}

View File

@ -1,54 +0,0 @@
/*
* 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,7 +225,31 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
/* USER CODE BEGIN 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 */
}
}
@ -263,6 +287,25 @@ void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi)
/* 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 */
}
}
@ -327,14 +370,14 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* htim_encoder)
}
/**
* @brief TIM_PWM MSP Initialization
* @brief TIM_Base MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_pwm: TIM_PWM handle pointer
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_pwm->Instance==TIM5)
if(htim_base->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspInit 0 */
@ -426,14 +469,14 @@ void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* htim_encoder)
}
/**
* @brief TIM_PWM MSP De-Initialization
* @brief TIM_Base MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param htim_pwm: TIM_PWM handle pointer
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
if(htim_pwm->Instance==TIM5)
if(htim_base->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspDeInit 0 */
@ -476,9 +519,6 @@ void HAL_UART_MspInit(UART_HandleTypeDef* huart)
GPIO_InitStruct.Alternate = GPIO_AF8_USART6;
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 END USART6_MspInit 1 */
@ -509,8 +549,6 @@ void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
*/
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 END USART6_MspDeInit 1 */

View File

@ -25,12 +25,12 @@
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_HandleTypeDef htim3;
TIM_HandleTypeDef htim2;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the TIM3 as a time base source.
* @brief This function configures the TIM2 as a time base source.
* The time source is configured to have 1ms time base with a dedicated
* Tick interrupt priority.
* @note This function is called automatically at the beginning of program after
@ -48,15 +48,15 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
HAL_StatusTypeDef status;
/* Enable TIM3 clock */
__HAL_RCC_TIM3_CLK_ENABLE();
/* Enable TIM2 clock */
__HAL_RCC_TIM2_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Get APB1 prescaler */
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
/* Compute TIM3 clock */
/* Compute TIM2 clock */
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
{
uwTimclock = HAL_RCC_GetPCLK1Freq();
@ -66,38 +66,38 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
uwTimclock = 2UL * HAL_RCC_GetPCLK1Freq();
}
/* Compute the prescaler value to have TIM3 counter clock equal to 1MHz */
/* Compute the prescaler value to have TIM2 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
/* Initialize TIM3 */
htim3.Instance = TIM3;
/* Initialize TIM2 */
htim2.Instance = TIM2;
/* Initialize TIMx peripheral as follow:
* Period = [(TIM3CLK/1000) - 1]. to have a (1/1000) s time base.
* Period = [(TIM2CLK/1000) - 1]. to have a (1/1000) s time base.
* Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
* ClockDivision = 0
* Counter direction = Up
*/
htim3.Init.Period = (1000000U / 1000U) - 1U;
htim3.Init.Prescaler = uwPrescalerValue;
htim3.Init.ClockDivision = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
htim2.Init.Period = (1000000U / 1000U) - 1U;
htim2.Init.Prescaler = uwPrescalerValue;
htim2.Init.ClockDivision = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
status = HAL_TIM_Base_Init(&htim3);
status = HAL_TIM_Base_Init(&htim2);
if (status == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
status = HAL_TIM_Base_Start_IT(&htim3);
status = HAL_TIM_Base_Start_IT(&htim2);
if (status == HAL_OK)
{
/* Enable the TIM3 global Interrupt */
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* Enable the TIM2 global Interrupt */
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
/* Configure the TIM IRQ priority */
HAL_NVIC_SetPriority(TIM3_IRQn, TickPriority, 0U);
HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
@ -113,25 +113,25 @@ HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
/**
* @brief Suspend Tick increment.
* @note Disable the tick increment by disabling TIM3 update interrupt.
* @note Disable the tick increment by disabling TIM2 update interrupt.
* @param None
* @retval None
*/
void HAL_SuspendTick(void)
{
/* Disable TIM3 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim3, TIM_IT_UPDATE);
/* Disable TIM2 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE);
}
/**
* @brief Resume Tick increment.
* @note Enable the tick increment by Enabling TIM3 update interrupt.
* @note Enable the tick increment by Enabling TIM2 update interrupt.
* @param None
* @retval None
*/
void HAL_ResumeTick(void)
{
/* Enable TIM3 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
/* Enable TIM2 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
}

View File

@ -58,8 +58,7 @@
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx;
extern SPI_HandleTypeDef hspi1;
extern UART_HandleTypeDef huart6;
extern TIM_HandleTypeDef htim3;
extern TIM_HandleTypeDef htim2;
/* USER CODE BEGIN EV */
@ -77,7 +76,8 @@ void NMI_Handler(void)
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1) {
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
}
@ -163,17 +163,17 @@ void DebugMon_Handler(void)
/******************************************************************************/
/**
* @brief This function handles TIM3 global interrupt.
* @brief This function handles TIM2 global interrupt.
*/
void TIM3_IRQHandler(void)
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM3_IRQn 0 */
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
}
/**
@ -218,20 +218,6 @@ void DMA2_Stream3_IRQHandler(void)
/* 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 END 1 */

View File

@ -1,44 +0,0 @@
# This is an genericBoard board with a single STM32F401CCUx chip
#
# Generated by STM32CubeIDE
# Take care that such file, as generated, may be overridden without any early notice. Please have a look to debug launch configuration setup(s)
source [find interface/stlink-dap.cfg]
set WORKAREASIZE 0x8000
transport select "dapdirect_swd"
set CHIPNAME STM32F401CCUx
set BOARDNAME genericBoard
# Enable debug when in low power modes
set ENABLE_LOW_POWER 1
# Stop Watchdog counters when halt
set STOP_WATCHDOG 1
# STlink Debug clock frequency
set CLOCK_FREQ 8000
# Reset configuration
# use hardware reset, connect under reset
# connect_assert_srst needed if low power mode application running (WFI...)
reset_config srst_only srst_nogate connect_assert_srst
set CONNECT_UNDER_RESET 1
set CORE_RESET 0
# ACCESS PORT NUMBER
set AP_NUM 0
# GDB PORT
set GDB_PORT 3333
# BCTM CPU variables
source [find target/stm32f4x.cfg]

View File

@ -26,13 +26,11 @@ Dma.SPI1_TX.1.PeriphInc=DMA_PINC_DISABLE
Dma.SPI1_TX.1.Priority=DMA_PRIORITY_LOW
Dma.SPI1_TX.1.RequestParameters=Instance,Direction,PeriphInc,MemInc,PeriphDataAlignment,MemDataAlignment,Mode,Priority,FIFOMode
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
FREERTOS.Mutexes01=display,Dynamic,NULL,Available
FREERTOS.Queues01=presses,16,char,0,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.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.configUSE_NEWLIB_REENTRANT=1
FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1
File.Version=6
GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false
@ -40,45 +38,52 @@ Mcu.CPN=STM32F401CCU6
Mcu.Family=STM32F4
Mcu.IP0=DMA
Mcu.IP1=FREERTOS
Mcu.IP10=USART6
Mcu.IP10=TIM5
Mcu.IP11=USART6
Mcu.IP2=I2C1
Mcu.IP3=NVIC
Mcu.IP4=RCC
Mcu.IP5=SPI1
Mcu.IP6=SYS
Mcu.IP7=TIM1
Mcu.IP8=TIM4
Mcu.IP9=TIM5
Mcu.IPNb=11
Mcu.IP6=SPI2
Mcu.IP7=SYS
Mcu.IP8=TIM1
Mcu.IP9=TIM4
Mcu.IPNb=12
Mcu.Name=STM32F401C(B-C)Ux
Mcu.Package=UFQFPN48
Mcu.Pin0=PC13-ANTI_TAMP
Mcu.Pin1=PA0-WKUP
Mcu.Pin10=PA8
Mcu.Pin11=PA9
Mcu.Pin12=PA10
Mcu.Pin13=PA11
Mcu.Pin14=PA12
Mcu.Pin15=PA13
Mcu.Pin16=PA14
Mcu.Pin17=PA15
Mcu.Pin18=PB3
Mcu.Pin19=PB4
Mcu.Pin10=PB2
Mcu.Pin11=PB10
Mcu.Pin12=PB14
Mcu.Pin13=PB15
Mcu.Pin14=PA8
Mcu.Pin15=PA9
Mcu.Pin16=PA10
Mcu.Pin17=PA11
Mcu.Pin18=PA12
Mcu.Pin19=PA13
Mcu.Pin2=PA1
Mcu.Pin20=PB6
Mcu.Pin21=PB7
Mcu.Pin22=PB8
Mcu.Pin23=PB9
Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V2
Mcu.Pin25=VP_SYS_VS_tim3
Mcu.Pin20=PA14
Mcu.Pin21=PA15
Mcu.Pin22=PB3
Mcu.Pin23=PB4
Mcu.Pin24=PB5
Mcu.Pin25=PB6
Mcu.Pin26=PB7
Mcu.Pin27=PB8
Mcu.Pin28=PB9
Mcu.Pin29=VP_FREERTOS_VS_CMSIS_V2
Mcu.Pin3=PA2
Mcu.Pin30=VP_SYS_VS_tim2
Mcu.Pin31=VP_TIM5_VS_ClockSourceINT
Mcu.Pin4=PA3
Mcu.Pin5=PA4
Mcu.Pin6=PA5
Mcu.Pin7=PA6
Mcu.Pin8=PA7
Mcu.Pin9=PB2
Mcu.PinsNb=26
Mcu.Pin9=PB1
Mcu.PinsNb=32
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F401CCUx
@ -100,10 +105,9 @@ NVIC.SavedPendsvIrqHandlerGenerated=true
NVIC.SavedSvcallIrqHandlerGenerated=true
NVIC.SavedSystickIrqHandlerGenerated=true
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
NVIC.TIM3_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
NVIC.TimeBase=TIM3_IRQn
NVIC.TimeBaseIP=TIM3
NVIC.USART6_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
NVIC.TIM2_IRQn=true\:15\:0\:false\:false\:true\:false\:false\:true\:true
NVIC.TimeBase=TIM2_IRQn
NVIC.TimeBaseIP=TIM2
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
PA0-WKUP.Signal=S_TIM5_CH1
PA1.Signal=S_TIM5_CH2
@ -138,6 +142,16 @@ PA7.Mode=Full_Duplex_Master
PA7.Signal=SPI1_MOSI
PA8.Signal=S_TIM1_CH1
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.GPIO_Label=DISPLAY_DC
PB2.Locked=true
@ -148,6 +162,10 @@ PB3.Signal=SYS_JTDO-SWO
PB4.Locked=true
PB4.Mode=JTAG_5_pins
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
PB7.Signal=S_TIM4_CH2
PB8.Mode=I2C
@ -155,7 +173,7 @@ PB8.Signal=I2C1_SCL
PB9.Mode=I2C
PB9.Signal=I2C1_SDA
PC13-ANTI_TAMP.GPIOParameters=GPIO_Label
PC13-ANTI_TAMP.GPIO_Label=LED_BLUE
PC13-ANTI_TAMP.GPIO_Label=LED
PC13-ANTI_TAMP.Locked=true
PC13-ANTI_TAMP.Signal=GPIO_Output
PinOutPanel.RotationAngle=0
@ -190,7 +208,7 @@ ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
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_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
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
RCC.AHBFreq_Value=16000000
RCC.APB1Freq_Value=16000000
RCC.APB2Freq_Value=16000000
@ -232,32 +250,30 @@ SPI1.Direction=SPI_DIRECTION_2LINES
SPI1.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,BaudRatePrescaler
SPI1.Mode=SPI_MODE_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.IC1Filter=15
TIM1.IC1Prescaler=TIM_ICPSC_DIV8
TIM1.IC2Filter=15
TIM1.IC2Prescaler=TIM_ICPSC_DIV8
TIM1.IPParameters=EncoderMode,IC1Prescaler,IC2Prescaler,IC2Filter,IC1Filter
TIM1.IPParameters=EncoderMode
TIM4.EncoderMode=TIM_ENCODERMODE_TI12
TIM4.IC1Filter=15
TIM4.IC1Prescaler=TIM_ICPSC_DIV8
TIM4.IC2Filter=15
TIM4.IC2Prescaler=TIM_ICPSC_DIV8
TIM4.IPParameters=EncoderMode,IC1Prescaler,IC1Filter,IC2Prescaler,IC2Filter
TIM4.IPParameters=EncoderMode
TIM5.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
TIM5.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
TIM5.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
TIM5.Channel-PWM\ Generation4\ CH4=TIM_CHANNEL_4
TIM5.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4,Prescaler,Period
TIM5.Period=10000
TIM5.Prescaler=92
TIM5.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,Channel-PWM Generation4 CH4
USART6.BaudRate=115200
USART6.IPParameters=VirtualMode,BaudRate
USART6.VirtualMode=VM_ASYNC
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
VP_SYS_VS_tim3.Mode=TIM3
VP_SYS_VS_tim3.Signal=SYS_VS_tim3
VP_SYS_VS_tim2.Mode=TIM2
VP_SYS_VS_tim2.Signal=SYS_VS_tim2
VP_TIM5_VS_ClockSourceINT.Mode=Internal
VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT
board=custom
rtos.0.ip=FREERTOS
isbadioc=false