Compare commits

..

8 Commits

Author SHA1 Message Date
80086edc13 Merge branch 'main' of https://git.lucacordes.com/lucordes/touchscreengames 2025-10-17 17:28:43 +02:00
fbfbcfde44 all 2025-10-17 17:28:14 +02:00
4b5e25f05e python script 2025-07-12 19:39:05 +02:00
d50fda1b23 adding the menu 2025-07-12 19:03:01 +02:00
dfbfc96e38 some changes. and cleanup 2025-07-12 17:22:17 +02:00
de2abc2cc7 ili931_touch.c 2025-07-11 10:54:57 +02:00
862fc8da97 understand freertos logging 2025-07-10 18:09:05 +02:00
b82393d4a2 idk 2025-07-10 18:00:34 +02:00
13 changed files with 912 additions and 700 deletions

View File

@ -51,6 +51,10 @@
#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"
@ -70,7 +74,9 @@
#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
@ -166,6 +172,12 @@ 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,18 +59,14 @@ void Error_Handler(void);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
#define LED_Pin GPIO_PIN_13
#define LED_GPIO_Port GPIOC
#define LED_BLUE_Pin GPIO_PIN_13
#define LED_BLUE_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,10 +52,11 @@ void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void DebugMon_Handler(void);
void TIM2_IRQHandler(void);
void TIM3_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

@ -1,20 +1,20 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
******************************************************************************
* File Name : freertos.c
* Description : Code for freertos applications
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
@ -52,6 +52,27 @@
/* 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 */

File diff suppressed because it is too large Load Diff

92
Core/Src/script.py Normal file
View File

@ -0,0 +1,92 @@
#!/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.")

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 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 */
}
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 */
}
}
@ -370,14 +327,14 @@ void HAL_TIM_Encoder_MspInit(TIM_HandleTypeDef* htim_encoder)
}
/**
* @brief TIM_Base MSP Initialization
* @brief TIM_PWM MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @param htim_pwm: TIM_PWM handle pointer
* @retval None
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef* htim_pwm)
{
if(htim_base->Instance==TIM5)
if(htim_pwm->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspInit 0 */
@ -469,14 +426,14 @@ void HAL_TIM_Encoder_MspDeInit(TIM_HandleTypeDef* htim_encoder)
}
/**
* @brief TIM_Base MSP De-Initialization
* @brief TIM_PWM MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @param htim_pwm: TIM_PWM handle pointer
* @retval None
*/
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
void HAL_TIM_PWM_MspDeInit(TIM_HandleTypeDef* htim_pwm)
{
if(htim_base->Instance==TIM5)
if(htim_pwm->Instance==TIM5)
{
/* USER CODE BEGIN TIM5_MspDeInit 0 */
@ -519,6 +476,9 @@ 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 */
@ -549,6 +509,8 @@ 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 htim2;
TIM_HandleTypeDef htim3;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/**
* @brief This function configures the TIM2 as a time base source.
* @brief This function configures the TIM3 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 TIM2 clock */
__HAL_RCC_TIM2_CLK_ENABLE();
/* Enable TIM3 clock */
__HAL_RCC_TIM3_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Get APB1 prescaler */
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
/* Compute TIM2 clock */
/* Compute TIM3 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 TIM2 counter clock equal to 1MHz */
/* Compute the prescaler value to have TIM3 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
/* Initialize TIM2 */
htim2.Instance = TIM2;
/* Initialize TIM3 */
htim3.Instance = TIM3;
/* Initialize TIMx peripheral as follow:
* Period = [(TIM2CLK/1000) - 1]. to have a (1/1000) s time base.
* Period = [(TIM3CLK/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
*/
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;
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;
status = HAL_TIM_Base_Init(&htim2);
status = HAL_TIM_Base_Init(&htim3);
if (status == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
status = HAL_TIM_Base_Start_IT(&htim2);
status = HAL_TIM_Base_Start_IT(&htim3);
if (status == HAL_OK)
{
/* Enable the TIM2 global Interrupt */
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* Enable the TIM3 global Interrupt */
HAL_NVIC_EnableIRQ(TIM3_IRQn);
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
/* Configure the TIM IRQ priority */
HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority, 0U);
HAL_NVIC_SetPriority(TIM3_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 TIM2 update interrupt.
* @note Disable the tick increment by disabling TIM3 update interrupt.
* @param None
* @retval None
*/
void HAL_SuspendTick(void)
{
/* Disable TIM2 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim2, TIM_IT_UPDATE);
/* Disable TIM3 update Interrupt */
__HAL_TIM_DISABLE_IT(&htim3, TIM_IT_UPDATE);
}
/**
* @brief Resume Tick increment.
* @note Enable the tick increment by Enabling TIM2 update interrupt.
* @note Enable the tick increment by Enabling TIM3 update interrupt.
* @param None
* @retval None
*/
void HAL_ResumeTick(void)
{
/* Enable TIM2 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim2, TIM_IT_UPDATE);
/* Enable TIM3 Update interrupt */
__HAL_TIM_ENABLE_IT(&htim3, TIM_IT_UPDATE);
}

View File

@ -1,20 +1,20 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
@ -58,7 +58,8 @@
extern DMA_HandleTypeDef hdma_spi1_rx;
extern DMA_HandleTypeDef hdma_spi1_tx;
extern SPI_HandleTypeDef hspi1;
extern TIM_HandleTypeDef htim2;
extern UART_HandleTypeDef huart6;
extern TIM_HandleTypeDef htim3;
/* USER CODE BEGIN EV */
@ -76,9 +77,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 TIM2 global interrupt.
* @brief This function handles TIM3 global interrupt.
*/
void TIM2_IRQHandler(void)
void TIM3_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE BEGIN TIM3_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM3_IRQn 0 */
HAL_TIM_IRQHandler(&htim3);
/* USER CODE BEGIN TIM3_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
/* USER CODE END TIM3_IRQn 1 */
}
/**
@ -218,6 +218,20 @@ 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

@ -0,0 +1,44 @@
# 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,11 +26,13 @@ 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
FREERTOS.IPParameters=Tasks01,FootprintOK,configUSE_NEWLIB_REENTRANT,Queues01,Mutexes01,configGENERATE_RUN_TIME_STATS,configUSE_STATS_FORMATTING_FUNCTIONS
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,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.configUSE_NEWLIB_REENTRANT=1
FREERTOS.configUSE_STATS_FORMATTING_FUNCTIONS=1
File.Version=6
GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false
@ -38,52 +40,45 @@ Mcu.CPN=STM32F401CCU6
Mcu.Family=STM32F4
Mcu.IP0=DMA
Mcu.IP1=FREERTOS
Mcu.IP10=TIM5
Mcu.IP11=USART6
Mcu.IP10=USART6
Mcu.IP2=I2C1
Mcu.IP3=NVIC
Mcu.IP4=RCC
Mcu.IP5=SPI1
Mcu.IP6=SPI2
Mcu.IP7=SYS
Mcu.IP8=TIM1
Mcu.IP9=TIM4
Mcu.IPNb=12
Mcu.IP6=SYS
Mcu.IP7=TIM1
Mcu.IP8=TIM4
Mcu.IP9=TIM5
Mcu.IPNb=11
Mcu.Name=STM32F401C(B-C)Ux
Mcu.Package=UFQFPN48
Mcu.Pin0=PC13-ANTI_TAMP
Mcu.Pin1=PA0-WKUP
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.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.Pin2=PA1
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.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.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=PB1
Mcu.PinsNb=32
Mcu.Pin9=PB2
Mcu.PinsNb=26
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F401CCUx
@ -105,9 +100,10 @@ NVIC.SavedPendsvIrqHandlerGenerated=true
NVIC.SavedSvcallIrqHandlerGenerated=true
NVIC.SavedSystickIrqHandlerGenerated=true
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.TimeBase=TIM2_IRQn
NVIC.TimeBaseIP=TIM2
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.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
PA0-WKUP.Signal=S_TIM5_CH1
PA1.Signal=S_TIM5_CH2
@ -142,16 +138,6 @@ 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
@ -162,10 +148,6 @@ 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
@ -173,7 +155,7 @@ PB8.Signal=I2C1_SCL
PB9.Mode=I2C
PB9.Signal=I2C1_SDA
PC13-ANTI_TAMP.GPIOParameters=GPIO_Label
PC13-ANTI_TAMP.GPIO_Label=LED
PC13-ANTI_TAMP.GPIO_Label=LED_BLUE
PC13-ANTI_TAMP.Locked=true
PC13-ANTI_TAMP.Signal=GPIO_Output
PinOutPanel.RotationAngle=0
@ -208,7 +190,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_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_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.APB1Freq_Value=16000000
RCC.APB2Freq_Value=16000000
@ -250,30 +232,32 @@ 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.IPParameters=EncoderMode
TIM1.IC1Filter=15
TIM1.IC1Prescaler=TIM_ICPSC_DIV8
TIM1.IC2Filter=15
TIM1.IC2Prescaler=TIM_ICPSC_DIV8
TIM1.IPParameters=EncoderMode,IC1Prescaler,IC2Prescaler,IC2Filter,IC1Filter
TIM4.EncoderMode=TIM_ENCODERMODE_TI12
TIM4.IPParameters=EncoderMode
TIM4.IC1Filter=15
TIM4.IC1Prescaler=TIM_ICPSC_DIV8
TIM4.IC2Filter=15
TIM4.IC2Prescaler=TIM_ICPSC_DIV8
TIM4.IPParameters=EncoderMode,IC1Prescaler,IC1Filter,IC2Prescaler,IC2Filter
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
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
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_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
VP_SYS_VS_tim3.Mode=TIM3
VP_SYS_VS_tim3.Signal=SYS_VS_tim3
board=custom
rtos.0.ip=FREERTOS
isbadioc=false