diff --git a/touchscreengames/Core/Inc/fonts.h b/touchscreengames/Core/Inc/fontsold.h similarity index 100% rename from touchscreengames/Core/Inc/fonts.h rename to touchscreengames/Core/Inc/fontsold.h diff --git a/touchscreengames/Core/Inc/st7735.h b/touchscreengames/Core/Inc/st7735.h new file mode 100644 index 0000000..b14f0da --- /dev/null +++ b/touchscreengames/Core/Inc/st7735.h @@ -0,0 +1,269 @@ +/* vim: set ai et ts=4 sw=4: */ +#ifndef __ST7735_H__ +#define __ST7735_H__ + +#include "fonts.h" +#include + +#ifndef __FONTS_H__ +#error "fonts.h not found or not included properly" +#endif + + +#define ST7735_MADCTL_MY 0x80 +#define ST7735_MADCTL_MX 0x40 +#define ST7735_MADCTL_MV 0x20 +#define ST7735_MADCTL_ML 0x10 +#define ST7735_MADCTL_RGB 0x00 +#define ST7735_MADCTL_BGR 0x08 +#define ST7735_MADCTL_MH 0x04 + +/*** Redefine if necessary ***/ +#define ST7735_SPI_PORT hspi2 +extern SPI_HandleTypeDef ST7735_SPI_PORT; + +#define ST7735_RES_Pin GPIO_PIN_10 +#define ST7735_RES_GPIO_Port GPIOA +#define ST7735_CS_Pin GPIO_PIN_4 +#define ST7735_CS_GPIO_Port GPIOA +#define ST7735_DC_Pin GPIO_PIN_2 +#define ST7735_DC_GPIO_Port GPIOB + +// AliExpress/eBay 1.8" display, default orientation + +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 160 +#define ST7735_XSTART 0 +#define ST7735_YSTART 0 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY) + + +// AliExpress/eBay 1.8" display, rotate right +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 160 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 0 +#define ST7735_YSTART 0 +#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV) +*/ + +// AliExpress/eBay 1.8" display, rotate left +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 160 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 0 +#define ST7735_YSTART 0 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV) +*/ + +// AliExpress/eBay 1.8" display, upside down +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 160 +#define ST7735_XSTART 0 +#define ST7735_YSTART 0 +#define ST7735_ROTATION (0) +*/ + +// WaveShare ST7735S-based 1.8" display, default orientation +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 160 +#define ST7735_XSTART 2 +#define ST7735_YSTART 1 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_RGB) +*/ + +// WaveShare ST7735S-based 1.8" display, rotate right +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 160 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 1 +#define ST7735_YSTART 2 +#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_RGB) +*/ + +// WaveShare ST7735S-based 1.8" display, rotate left +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 160 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 1 +#define ST7735_YSTART 2 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_RGB) +*/ + +// WaveShare ST7735S-based 1.8" display, upside down +/* +#define ST7735_IS_160X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 160 +#define ST7735_XSTART 2 +#define ST7735_YSTART 1 +#define ST7735_ROTATION (ST7735_MADCTL_RGB) +*/ + +// 1.44" display, default orientation +//#define ST7735_IS_128X128 1 +//#define ST7735_WIDTH 128 +//#define ST7735_HEIGHT 128 +//#define ST7735_XSTART 2 +//#define ST7735_YSTART 3 +//#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR) + +// 1.44" display, rotate right +/* +#define ST7735_IS_128X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 3 +#define ST7735_YSTART 2 +#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR) +*/ + +// 1.44" display, rotate left +/* +#define ST7735_IS_128X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 1 +#define ST7735_YSTART 2 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR) +*/ + +// 1.44" display, upside down +/* +#define ST7735_IS_128X128 1 +#define ST7735_WIDTH 128 +#define ST7735_HEIGHT 128 +#define ST7735_XSTART 2 +#define ST7735_YSTART 1 +#define ST7735_ROTATION (ST7735_MADCTL_BGR) +*/ + +// mini 160x80 display (it's unlikely you want the default orientation) +/* +#define ST7735_IS_160X80 1 +#define ST7735_XSTART 26 +#define ST7735_YSTART 1 +#define ST7735_WIDTH 80 +#define ST7735_HEIGHT 160 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MY | ST7735_MADCTL_BGR) +*/ + +// mini 160x80, rotate left +/* +#define ST7735_IS_160X80 1 +#define ST7735_XSTART 1 +#define ST7735_YSTART 26 +#define ST7735_WIDTH 160 +#define ST7735_HEIGHT 80 +#define ST7735_ROTATION (ST7735_MADCTL_MX | ST7735_MADCTL_MV | ST7735_MADCTL_BGR) +*/ + +// mini 160x80, rotate right +/* +#define ST7735_IS_160X80 1 +#define ST7735_XSTART 1 +#define ST7735_YSTART 26 +#define ST7735_WIDTH 160 +#define ST7735_HEIGHT 80 +#define ST7735_ROTATION (ST7735_MADCTL_MY | ST7735_MADCTL_MV | ST7735_MADCTL_BGR) +*/ + +/****************************/ + +#define ST7735_NOP 0x00 +#define ST7735_SWRESET 0x01 +#define ST7735_RDDID 0x04 +#define ST7735_RDDST 0x09 + +#define ST7735_SLPIN 0x10 +#define ST7735_SLPOUT 0x11 +#define ST7735_PTLON 0x12 +#define ST7735_NORON 0x13 + +#define ST7735_INVOFF 0x20 +#define ST7735_INVON 0x21 +#define ST7735_GAMSET 0x26 +#define ST7735_DISPOFF 0x28 +#define ST7735_DISPON 0x29 +#define ST7735_CASET 0x2A +#define ST7735_RASET 0x2B +#define ST7735_RAMWR 0x2C +#define ST7735_RAMRD 0x2E + +#define ST7735_PTLAR 0x30 +#define ST7735_COLMOD 0x3A +#define ST7735_MADCTL 0x36 + +#define ST7735_FRMCTR1 0xB1 +#define ST7735_FRMCTR2 0xB2 +#define ST7735_FRMCTR3 0xB3 +#define ST7735_INVCTR 0xB4 +#define ST7735_DISSET5 0xB6 + +#define ST7735_PWCTR1 0xC0 +#define ST7735_PWCTR2 0xC1 +#define ST7735_PWCTR3 0xC2 +#define ST7735_PWCTR4 0xC3 +#define ST7735_PWCTR5 0xC4 +#define ST7735_VMCTR1 0xC5 + +#define ST7735_RDID1 0xDA +#define ST7735_RDID2 0xDB +#define ST7735_RDID3 0xDC +#define ST7735_RDID4 0xDD + +#define ST7735_PWCTR6 0xFC + +#define ST7735_GMCTRP1 0xE0 +#define ST7735_GMCTRN1 0xE1 + +// Color definitions +#define ST7735_BLACK 0x0000 +#define ST7735_BLUE 0x001F +#define ST7735_RED 0xF800 +#define ST7735_GREEN 0x07E0 +#define ST7735_CYAN 0x07FF +#define ST7735_MAGENTA 0xF81F +#define ST7735_YELLOW 0xFFE0 +#define ST7735_WHITE 0xFFFF +#define ST7735_COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)) + +typedef enum { + GAMMA_10 = 0x01, + GAMMA_25 = 0x02, + GAMMA_22 = 0x04, + GAMMA_18 = 0x08 +} GammaDef; + +#ifdef __cplusplus +extern "C" { +#endif + +// call before initializing any SPI devices +void ST7735_Unselect(); + +void ST7735_Init(void); +void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color); +void ST7735_WriteString(uint16_t x, uint16_t y, const char* str, FontDef font, uint16_t color, uint16_t bgcolor); +void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); +void ST7735_FillRectangleFast(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color); +void ST7735_FillScreen(uint16_t color); +void ST7735_FillScreenFast(uint16_t color); +void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data); +void ST7735_InvertColors(bool invert); +void ST7735_SetGamma(GammaDef gamma); + +#ifdef __cplusplus +} +#endif + +#endif // __ST7735_H__ diff --git a/touchscreengames/Core/Src/fonts.c b/touchscreengames/Core/Src/fontsold.c similarity index 100% rename from touchscreengames/Core/Src/fonts.c rename to touchscreengames/Core/Src/fontsold.c diff --git a/touchscreengames/Core/Src/main.c b/touchscreengames/Core/Src/main.c index 626e216..c8992b7 100644 --- a/touchscreengames/Core/Src/main.c +++ b/touchscreengames/Core/Src/main.c @@ -23,9 +23,12 @@ /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ //#include "ili9341.h" -#include "ILI9341_STM32_Driver.h" -#include "ILI9341_GFX.h" -#include "snake.h" +//#include "ILI9341_STM32_Driver.h" +//#include "ILI9341_GFX.h" +//#include "snake.h" +#include +#include "st7735.h" +#include "fonts.h" /* USER CODE END Includes */ @@ -307,6 +310,13 @@ void set_pwm(float duty, char motor, char mode) { } } } +void init() { + ST7735_Init(); + + const char ready[] = "Ready!\r\n"; + ST7735_FillScreen(ST7735_GREEN); + +} /* USER CODE END 0 */ /** @@ -345,51 +355,51 @@ int main(void) { MX_SPI2_Init(); MX_TIM1_Init(); /* USER CODE BEGIN 2 */ - ILI9341_Init(); - ILI9341_SetRotation(SCREEN_HORIZONTAL_1); +// ILI9341_Init(); +// ILI9341_SetRotation(SCREEN_HORIZONTAL_1); //ILI9341_FillScreen(WHITE); //void XPT2046_Init(); //Flash_Write_HighScore(100); /* USER CODE END 2 */ /* Init scheduler */ - osKernelInitialize(); - /* Create the mutex(es) */ - /* creation of display */ - displayHandle = osMutexNew(&display_attributes); - - /* USER CODE BEGIN RTOS_MUTEX */ - /* add mutexes, ... */ - /* USER CODE END RTOS_MUTEX */ - - /* USER CODE BEGIN RTOS_SEMAPHORES */ - /* add semaphores, ... */ - /* USER CODE END RTOS_SEMAPHORES */ - - /* USER CODE BEGIN RTOS_TIMERS */ - /* start timers, add new ones, ... */ - /* USER CODE END RTOS_TIMERS */ - - /* Create the queue(s) */ - /* creation of presses */ - pressesHandle = osMessageQueueNew(16, sizeof(char), &presses_attributes); - - /* USER CODE BEGIN RTOS_QUEUES */ - /* add queues, ... */ - /* USER CODE END RTOS_QUEUES */ - - /* Create the thread(s) */ - /* creation of control */ - controlHandle = osThreadNew(start_control, NULL, &control_attributes); - - /* creation of draw */ - drawHandle = osThreadNew(snakegame, NULL, &draw_attributes); - - /* creation of menu */ - menuHandle = osThreadNew(handle_menu, NULL, &menu_attributes); - - /* creation of balance */ - balanceHandle = osThreadNew(start_balance, NULL, &balance_attributes); +// osKernelInitialize(); +// /* Create the mutex(es) */ +// /* creation of display */ +// displayHandle = osMutexNew(&display_attributes); +// +// /* USER CODE BEGIN RTOS_MUTEX */ +// /* add mutexes, ... */ +// /* USER CODE END RTOS_MUTEX */ +// +// /* USER CODE BEGIN RTOS_SEMAPHORES */ +// /* add semaphores, ... */ +// /* USER CODE END RTOS_SEMAPHORES */ +// +// /* USER CODE BEGIN RTOS_TIMERS */ +// /* start timers, add new ones, ... */ +// /* USER CODE END RTOS_TIMERS */ +// +// /* Create the queue(s) */ +// /* creation of presses */ +// pressesHandle = osMessageQueueNew(16, sizeof(char), &presses_attributes); +// +// /* USER CODE BEGIN RTOS_QUEUES */ +// /* add queues, ... */ +// /* USER CODE END RTOS_QUEUES */ +// +// /* Create the thread(s) */ +// /* creation of control */ +// controlHandle = osThreadNew(start_control, NULL, &control_attributes); +// +// /* creation of draw */ +// drawHandle = osThreadNew(snakegame, NULL, &draw_attributes); +// +// /* creation of menu */ +// menuHandle = osThreadNew(handle_menu, NULL, &menu_attributes); +// +// /* creation of balance */ +// balanceHandle = osThreadNew(start_balance, NULL, &balance_attributes); /* USER CODE BEGIN RTOS_THREADS */ /* add threads, ... */ @@ -408,10 +418,10 @@ int main(void) { /* USER CODE BEGIN RTOS_EVENTS */ /* add events, ... */ /* USER CODE END RTOS_EVENTS */ - + ST7735_FillScreen(ST7735_GREEN); /* Start scheduler */ osKernelStart(); - + ST7735_FillScreen(ST7735_GREEN); /* We should never get here as control is now taken by the scheduler */ /* Infinite loop */ @@ -426,14 +436,23 @@ int main(void) { //while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY) //; + ST7735_Init(); + uint8_t cmd = 0x01; // Software reset + HAL_SPI_Transmit(&ST7735_SPI_PORT, &cmd, 1, HAL_MAX_DELAY); while (1) { + // Check border + ST7735_FillScreen(ST7735_BLACK); + for(int x = 0; x < ST7735_WIDTH; x++) { + ST7735_DrawPixel(x, 0, ST7735_RED); + ST7735_DrawPixel(x, ST7735_HEIGHT-1, ST7735_RED); + } /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ //tempspeed = encoder_TIM4_speed_rad(); - HAL_Delay(10); + HAL_Delay(1000); } /* USER CODE END 3 */ @@ -534,7 +553,7 @@ static void MX_SPI2_Init(void) { hspi2.Init.CLKPolarity = SPI_POLARITY_LOW; hspi2.Init.CLKPhase = SPI_PHASE_1EDGE; hspi2.Init.NSS = SPI_NSS_SOFT; - hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi2.Init.TIMode = SPI_TIMODE_DISABLE; hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; @@ -867,9 +886,15 @@ void start_control(void *argument) { static char statsBuffer[200]; motor.ul = 0.0 * M_PI; motor.ur = 0.0 * M_PI; - + init(); for (;;) { vTaskDelay(TSmillis); + vTaskDelay(500); + ST7735_Init(); + uint8_t test = 0x11; // SLPOUT + HAL_SPI_Transmit(&hspi2, &test, 1, HAL_MAX_DELAY); + ST7735_InvertColors(1); + vTaskGetRunTimeStats(statsBuffer); //motor.wr = encoder_TIM3_speed_rad(); @@ -995,61 +1020,62 @@ void snakegame(void *argument) { * @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" } }; +//#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 + vTaskDelay(50); // 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); - } - } - } +// 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); +// } +// } +// } } @@ -1060,85 +1086,85 @@ void handle_menu(void *argument) { char dir; vTaskDelay(50); - redraw_menu(); - while (1) { - // Check input - if (run_menu) { - 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]) { - if (osMutexAcquire(displayHandle, osWaitForever) - == osOK) { - - 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); - osMutexRelease(displayHandle); - } - } else { - if (osMutexAcquire(displayHandle, osWaitForever) - == osOK) { - - 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); - osMutexRelease(displayHandle); - - } - } - } - 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]) { - if (osMutexAcquire(displayHandle, osWaitForever) == osOK) { - - 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); - osMutexRelease(displayHandle); - - } - - } else { - if (osMutexAcquire(displayHandle, osWaitForever) == osOK) { - - 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); - osMutexRelease(displayHandle); - - } - - } - if (redraw_menu_pending) { - redraw_menu(); - redraw_menu_pending = 0; - } - } - - osDelay(10); - } +// redraw_menu(); +// while (1) { +// // Check input +// if (run_menu) { +// 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]) { +// if (osMutexAcquire(displayHandle, osWaitForever) +// == osOK) { +// +//// 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); +// osMutexRelease(displayHandle); +// } +// } else { +// if (osMutexAcquire(displayHandle, osWaitForever) +// == osOK) { +// +//// 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); +// osMutexRelease(displayHandle); +// +// } +// } +// } +// 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]) { +// if (osMutexAcquire(displayHandle, osWaitForever) == osOK) { +// +//// 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); +// osMutexRelease(displayHandle); +// +// } +// +// } else { +// if (osMutexAcquire(displayHandle, osWaitForever) == osOK) { +// +//// 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); +// osMutexRelease(displayHandle); +// +// } +// +// } +// if (redraw_menu_pending) { +// redraw_menu(); +// redraw_menu_pending = 0; +// } +// } +// +// osDelay(10); +// } /* USER CODE END handle_menu */ } @@ -1265,10 +1291,11 @@ void start_balance(void *argument) { } else { //motor.ur = 0; - //motor.ul = motor.ur; + //motor.ul = motor.ur set_pwm(0, 'l', 'c'); set_pwm(0, 'r', 'c'); } + ST7735_FillScreen(ST7735_GREEN); } /* USER CODE END start_balance */ diff --git a/touchscreengames/Core/Src/st7735.c b/touchscreengames/Core/Src/st7735.c new file mode 100644 index 0000000..505b5e0 --- /dev/null +++ b/touchscreengames/Core/Src/st7735.c @@ -0,0 +1,312 @@ +/* vim: set ai et ts=4 sw=4: */ +#include "stm32f4xx_hal.h" +#include "st7735.h" +#include "malloc.h" +#include "string.h" + +#define DELAY 0x80 + +// based on Adafruit ST7735 library for Arduino +static const uint8_t + init_cmds1[] = { // Init for 7735R, part 1 (red or green tab) + 15, // 15 commands in list: + ST7735_SWRESET, DELAY, // 1: Software reset, 0 args, w/delay + 150, // 150 ms delay + ST7735_SLPOUT , DELAY, // 2: Out of sleep mode, 0 args, w/delay + 255, // 500 ms delay + ST7735_FRMCTR1, 3 , // 3: Frame rate ctrl - normal mode, 3 args: + 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) + ST7735_FRMCTR2, 3 , // 4: Frame rate control - idle mode, 3 args: + 0x01, 0x2C, 0x2D, // Rate = fosc/(1x2+40) * (LINE+2C+2D) + ST7735_FRMCTR3, 6 , // 5: Frame rate ctrl - partial mode, 6 args: + 0x01, 0x2C, 0x2D, // Dot inversion mode + 0x01, 0x2C, 0x2D, // Line inversion mode + ST7735_INVCTR , 1 , // 6: Display inversion ctrl, 1 arg, no delay: + 0x07, // No inversion + ST7735_PWCTR1 , 3 , // 7: Power control, 3 args, no delay: + 0xA2, + 0x02, // -4.6V + 0x84, // AUTO mode + ST7735_PWCTR2 , 1 , // 8: Power control, 1 arg, no delay: + 0xC5, // VGH25 = 2.4C VGSEL = -10 VGH = 3 * AVDD + ST7735_PWCTR3 , 2 , // 9: Power control, 2 args, no delay: + 0x0A, // Opamp current small + 0x00, // Boost frequency + ST7735_PWCTR4 , 2 , // 10: Power control, 2 args, no delay: + 0x8A, // BCLK/2, Opamp current small & Medium low + 0x2A, + ST7735_PWCTR5 , 2 , // 11: Power control, 2 args, no delay: + 0x8A, 0xEE, + ST7735_VMCTR1 , 1 , // 12: Power control, 1 arg, no delay: + 0x0E, + ST7735_INVOFF , 0 , // 13: Don't invert display, no args, no delay + ST7735_MADCTL , 1 , // 14: Memory access control (directions), 1 arg: + ST7735_ROTATION, // row addr/col addr, bottom to top refresh + ST7735_COLMOD , 1 , // 15: set color mode, 1 arg, no delay: + 0x05 }, // 16-bit color + +#if (defined(ST7735_IS_128X128) || defined(ST7735_IS_160X128)) + init_cmds2[] = { // Init for 7735R, part 2 (1.44" display) + 2, // 2 commands in list: + ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 0x7F, // XEND = 127 + ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 0x7F }, // XEND = 127 +#endif // ST7735_IS_128X128 + +#ifdef ST7735_IS_160X80 + init_cmds2[] = { // Init for 7735S, part 2 (160x80 display) + 3, // 3 commands in list: + ST7735_CASET , 4 , // 1: Column addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 0x4F, // XEND = 79 + ST7735_RASET , 4 , // 2: Row addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 0x9F , // XEND = 159 + ST7735_INVON, 0 }, // 3: Invert colors +#endif + + init_cmds3[] = { // Init for 7735R, part 3 (red or green tab) + 4, // 4 commands in list: + ST7735_GMCTRP1, 16 , // 1: Gamma Adjustments (pos. polarity), 16 args, no delay: + 0x02, 0x1c, 0x07, 0x12, + 0x37, 0x32, 0x29, 0x2d, + 0x29, 0x25, 0x2B, 0x39, + 0x00, 0x01, 0x03, 0x10, + ST7735_GMCTRN1, 16 , // 2: Gamma Adjustments (neg. polarity), 16 args, no delay: + 0x03, 0x1d, 0x07, 0x06, + 0x2E, 0x2C, 0x29, 0x2D, + 0x2E, 0x2E, 0x37, 0x3F, + 0x00, 0x00, 0x02, 0x10, + ST7735_NORON , DELAY, // 3: Normal display on, no args, w/delay + 10, // 10 ms delay + ST7735_DISPON , DELAY, // 4: Main screen turn on, no args w/delay + 100 }; // 100 ms delay + +static void ST7735_Select() { + HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_RESET); +} + +void ST7735_Unselect() { + HAL_GPIO_WritePin(ST7735_CS_GPIO_Port, ST7735_CS_Pin, GPIO_PIN_SET); +} + +static void ST7735_Reset() { + HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_RESET); + HAL_Delay(5); + HAL_GPIO_WritePin(ST7735_RES_GPIO_Port, ST7735_RES_Pin, GPIO_PIN_SET); +} + +static void ST7735_WriteCommand(uint8_t cmd) { + HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_RESET); + HAL_SPI_Transmit(&ST7735_SPI_PORT, &cmd, sizeof(cmd), HAL_MAX_DELAY); +} + +static void ST7735_WriteData(uint8_t* buff, size_t buff_size) { + HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET); + HAL_SPI_Transmit(&ST7735_SPI_PORT, buff, buff_size, HAL_MAX_DELAY); +} + +static void ST7735_ExecuteCommandList(const uint8_t *addr) { + uint8_t numCommands, numArgs; + uint16_t ms; + + numCommands = *addr++; + while(numCommands--) { + uint8_t cmd = *addr++; + ST7735_WriteCommand(cmd); + + numArgs = *addr++; + // If high bit set, delay follows args + ms = numArgs & DELAY; + numArgs &= ~DELAY; + if(numArgs) { + ST7735_WriteData((uint8_t*)addr, numArgs); + addr += numArgs; + } + + if(ms) { + ms = *addr++; + if(ms == 255) ms = 500; + HAL_Delay(ms); + } + } +} + +static void ST7735_SetAddressWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1) { + // column address set + ST7735_WriteCommand(ST7735_CASET); + uint8_t data[] = { 0x00, x0 + ST7735_XSTART, 0x00, x1 + ST7735_XSTART }; + ST7735_WriteData(data, sizeof(data)); + + // row address set + ST7735_WriteCommand(ST7735_RASET); + data[1] = y0 + ST7735_YSTART; + data[3] = y1 + ST7735_YSTART; + ST7735_WriteData(data, sizeof(data)); + + // write to RAM + ST7735_WriteCommand(ST7735_RAMWR); +} + +void ST7735_Init() { + ST7735_Select(); + ST7735_Reset(); + ST7735_ExecuteCommandList(init_cmds1); + ST7735_ExecuteCommandList(init_cmds2); + ST7735_ExecuteCommandList(init_cmds3); + ST7735_Unselect(); +} + +void ST7735_DrawPixel(uint16_t x, uint16_t y, uint16_t color) { + if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT)) + return; + + ST7735_Select(); + + ST7735_SetAddressWindow(x, y, x+1, y+1); + uint8_t data[] = { color >> 8, color & 0xFF }; + ST7735_WriteData(data, sizeof(data)); + + ST7735_Unselect(); +} + +static void ST7735_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor) { + uint32_t i, b, j; + + ST7735_SetAddressWindow(x, y, x+font.width-1, y+font.height-1); + + for(i = 0; i < font.height; i++) { + b = font.data[(ch - 32) * font.height + i]; + for(j = 0; j < font.width; j++) { + if((b << j) & 0x8000) { + uint8_t data[] = { color >> 8, color & 0xFF }; + ST7735_WriteData(data, sizeof(data)); + } else { + uint8_t data[] = { bgcolor >> 8, bgcolor & 0xFF }; + ST7735_WriteData(data, sizeof(data)); + } + } + } +} + +/* +Simpler (and probably slower) implementation: + +static void ST7735_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color) { + uint32_t i, b, j; + + for(i = 0; i < font.height; i++) { + b = font.data[(ch - 32) * font.height + i]; + for(j = 0; j < font.width; j++) { + if((b << j) & 0x8000) { + ST7735_DrawPixel(x + j, y + i, color); + } + } + } +} +*/ + +void ST7735_WriteString(uint16_t x, uint16_t y, const char* str, FontDef font, uint16_t color, uint16_t bgcolor) { + ST7735_Select(); + + while(*str) { + if(x + font.width >= ST7735_WIDTH) { + x = 0; + y += font.height; + if(y + font.height >= ST7735_HEIGHT) { + break; + } + + if(*str == ' ') { + // skip spaces in the beginning of the new line + str++; + continue; + } + } + + ST7735_WriteChar(x, y, *str, font, color, bgcolor); + x += font.width; + str++; + } + + ST7735_Unselect(); +} + +void ST7735_FillRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { + // clipping + if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT)) return; + if((x + w - 1) >= ST7735_WIDTH) w = ST7735_WIDTH - x; + if((y + h - 1) >= ST7735_HEIGHT) h = ST7735_HEIGHT - y; + + ST7735_Select(); + ST7735_SetAddressWindow(x, y, x+w-1, y+h-1); + + uint8_t data[] = { color >> 8, color & 0xFF }; + HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET); + for(y = h; y > 0; y--) { + for(x = w; x > 0; x--) { + HAL_SPI_Transmit(&ST7735_SPI_PORT, data, sizeof(data), HAL_MAX_DELAY); + } + } + + ST7735_Unselect(); +} + +void ST7735_FillRectangleFast(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color) { + // clipping + if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT)) return; + if((x + w - 1) >= ST7735_WIDTH) w = ST7735_WIDTH - x; + if((y + h - 1) >= ST7735_HEIGHT) h = ST7735_HEIGHT - y; + + ST7735_Select(); + ST7735_SetAddressWindow(x, y, x+w-1, y+h-1); + + // Prepare whole line in a single buffer + uint8_t pixel[] = { color >> 8, color & 0xFF }; + uint8_t *line = malloc(w * sizeof(pixel)); + for(x = 0; x < w; ++x) + memcpy(line + x * sizeof(pixel), pixel, sizeof(pixel)); + + HAL_GPIO_WritePin(ST7735_DC_GPIO_Port, ST7735_DC_Pin, GPIO_PIN_SET); + for(y = h; y > 0; y--) + HAL_SPI_Transmit(&ST7735_SPI_PORT, line, w * sizeof(pixel), HAL_MAX_DELAY); + + free(line); + ST7735_Unselect(); +} + +void ST7735_FillScreen(uint16_t color) { + ST7735_FillRectangle(0, 0, ST7735_WIDTH, ST7735_HEIGHT, color); +} + +void ST7735_FillScreenFast(uint16_t color) { + ST7735_FillRectangleFast(0, 0, ST7735_WIDTH, ST7735_HEIGHT, color); +} + +void ST7735_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data) { + if((x >= ST7735_WIDTH) || (y >= ST7735_HEIGHT)) return; + if((x + w - 1) >= ST7735_WIDTH) return; + if((y + h - 1) >= ST7735_HEIGHT) return; + + ST7735_Select(); + ST7735_SetAddressWindow(x, y, x+w-1, y+h-1); + ST7735_WriteData((uint8_t*)data, sizeof(uint16_t)*w*h); + ST7735_Unselect(); +} + +void ST7735_InvertColors(bool invert) { + ST7735_Select(); + ST7735_WriteCommand(invert ? ST7735_INVON : ST7735_INVOFF); + ST7735_Unselect(); +} + +void ST7735_SetGamma(GammaDef gamma) +{ + ST7735_Select(); + ST7735_WriteCommand(ST7735_GAMSET); + ST7735_WriteData((uint8_t *) &gamma, sizeof(gamma)); + ST7735_Unselect(); +}