From fdf1a42bba882acc87db3bdd322f4458367d0952 Mon Sep 17 00:00:00 2001 From: Clyne Sullivan Date: Sun, 29 Nov 2020 08:04:13 -0500 Subject: [PATCH] display optimization; sprites --- STM32L011x4.ld | 1 + buttons.h | 9 +++ cfg/halconf.h | 10 +-- cfg/mcuconf.h | 2 +- dogs.c | 71 ++++++++++++++++++---- dogs.h | 3 + main.c | 162 +++++++++++++++++++++++++++++-------------------- 7 files changed, 174 insertions(+), 84 deletions(-) diff --git a/STM32L011x4.ld b/STM32L011x4.ld index c583d02..5fec90f 100644 --- a/STM32L011x4.ld +++ b/STM32L011x4.ld @@ -79,6 +79,7 @@ REGION_ALIAS("DATA_RAM_LMA", flash0); REGION_ALIAS("BSS_RAM", ram0); /* RAM region to be used for the default heap.*/ +/* tcsullivan: Set to ram1 so bss reports actual size used. */ REGION_ALIAS("HEAP_RAM", ram1); /* Generic rules inclusion.*/ diff --git a/buttons.h b/buttons.h index bade3cf..62fc364 100644 --- a/buttons.h +++ b/buttons.h @@ -12,6 +12,15 @@ #ifndef BUTTONS_H_ #define BUTTONS_H_ +#define BUTTON_JOYUL (1 << 7) +#define BUTTON_JOYUR (1 << 6) +#define BUTTON_JOYDR (1 << 5) +#define BUTTON_JOYDL (1 << 4) +#define BUTTON_JOY (1 << 3) +#define BUTTON_1 (1 << 2) +#define BUTTON_2 (1 << 1) +#define BUTTON_3 (1 << 0) + extern unsigned char button_state; void buttons_init(); diff --git a/cfg/halconf.h b/cfg/halconf.h index 4d6ea7e..fe4c478 100644 --- a/cfg/halconf.h +++ b/cfg/halconf.h @@ -142,7 +142,7 @@ * @brief Enables the SERIAL subsystem. */ #if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) -#define HAL_USE_SERIAL TRUE +#define HAL_USE_SERIAL FALSE #endif /** @@ -230,7 +230,7 @@ * @note Disabling this option saves both code and data space. */ #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) -#define ADC_USE_WAIT TRUE +#define ADC_USE_WAIT FALSE #endif /** @@ -238,7 +238,7 @@ * @note Disabling this option saves both code and data space. */ #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define ADC_USE_MUTUAL_EXCLUSION TRUE +#define ADC_USE_MUTUAL_EXCLUSION FALSE #endif /*===========================================================================*/ @@ -447,7 +447,7 @@ * @note Disabling this option saves both code and data space. */ #if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) -#define SPI_USE_WAIT TRUE +#define SPI_USE_WAIT FALSE #endif /** @@ -463,7 +463,7 @@ * @note Disabling this option saves both code and data space. */ #if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define SPI_USE_MUTUAL_EXCLUSION TRUE +#define SPI_USE_MUTUAL_EXCLUSION FALSE #endif /** diff --git a/cfg/mcuconf.h b/cfg/mcuconf.h index ccb4a6f..f02fe10 100644 --- a/cfg/mcuconf.h +++ b/cfg/mcuconf.h @@ -131,7 +131,7 @@ * SERIAL driver system settings. */ #define STM32_SERIAL_USE_USART2 FALSE -#define STM32_SERIAL_USE_LPUART1 TRUE +#define STM32_SERIAL_USE_LPUART1 FALSE /* * SPI driver system settings. diff --git a/dogs.c b/dogs.c index 9f754d6..b401c39 100644 --- a/dogs.c +++ b/dogs.c @@ -17,10 +17,16 @@ #define SET_CMD palClearPad(GPIOC, 15) #define CS_HIGH palSetPad(GPIOA, 4) #define CS_LOW palClearPad(GPIOA, 4) - unsigned char dogs_buffer[DISP_WIDTH * DISP_HEIGHT / 8]; +static volatile bool dogs_spi_done = false; + static void dogs_init_display(); +static void dogs_spi_callback(SPIDriver *spid) +{ + if (spiIsBufferComplete(spid)) + dogs_spi_done = true; +} void dogs_init() { @@ -35,27 +41,32 @@ void dogs_init() palSetPad(GPIOC, 14); palClearPad(GPIOC, 15); - static const SPIConfig ls_spicfg = { + static const SPIConfig spicfg = { false, - NULL, - SPI_CR1_BR_2 | SPI_CR1_BR_1, + dogs_spi_callback, + 0, // cr1 0 }; - spiStart(&SPID1, &ls_spicfg); + spiStart(&SPID1, &spicfg); dogs_init_display(); dogs_clear(); + dogs_flush(); } void dogs_write_data(unsigned char byte) { SET_DATA; - spiSend(&SPID1, 1, &byte); + dogs_spi_done = false; + spiStartSend(&SPID1, 1, &byte); + while (!dogs_spi_done); } void dogs_write_cmd(unsigned char byte) { SET_CMD; - spiSend(&SPID1, 1, &byte); + dogs_spi_done = false; + spiStartSend(&SPID1, 1, &byte); + while (!dogs_spi_done); } void dogs_set_column(unsigned int col) @@ -144,10 +155,17 @@ void dogs_init_display() void dogs_clear() { unsigned char *ptr = dogs_buffer; - for (unsigned int i = 0; i < sizeof(dogs_buffer); i++) { + unsigned int count = sizeof(dogs_buffer); + for (; count > 8; count -= 8) { + *ptr++ = 0; + *ptr++ = 0; + *ptr++ = 0; + *ptr++ = 0; + *ptr++ = 0; + *ptr++ = 0; + *ptr++ = 0; *ptr++ = 0; } - dogs_flush(); } void dogs_flush() @@ -157,9 +175,40 @@ void dogs_flush() for (int page = 0; page < 8; page++) { dogs_set_page(page); dogs_set_column(30); - for (int i = 0; i < 102; i++) - dogs_write_data(*ptr++); + + SET_DATA; + dogs_spi_done = false; + spiStartSend(&SPID1, 102, ptr); + ptr += 102; + while (!dogs_spi_done); } CS_HIGH; } +void draw_pixel(int x, int y, bool state) +{ + if (state) + dogs_buffer[y / 8 * DISP_WIDTH + x] |= (1 << (y % 8)); + else + dogs_buffer[y / 8 * DISP_WIDTH + x] &= ~(1 << (y % 8)); +} + +void draw_bitmap(int x, int y, const unsigned char *buffer) +{ + // Prepare source information + const unsigned char *src = buffer; + const int width = *src++; + const int height = *src++; + int sbit = 0; + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + draw_pixel(x + i, y + j, *src & (1 << sbit)); + if (++sbit == 8) { + sbit = 0; + ++src; + } + } + } +} + diff --git a/dogs.h b/dogs.h index 2660bf1..1ae24bb 100644 --- a/dogs.h +++ b/dogs.h @@ -21,5 +21,8 @@ void dogs_init(); void dogs_clear(); void dogs_flush(); +void draw_pixel(int x, int y, bool state); +void draw_bitmap(int x, int y, const unsigned char *buffer); + #endif // DOGS_H_ diff --git a/main.c b/main.c index 126c47e..e7949a8 100644 --- a/main.c +++ b/main.c @@ -1,67 +1,95 @@ -/** - * main.c - Firmware entry point and main loop for game or testing. - * Copyright (C) 2020 Clyne Sullivan - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * See the GNU General Public License for more details. - */ - -#include "buttons.h" -#include "ch.h" -#include "dogs.h" -#include "hal.h" - -/* - * Progress: - * - Serial through LPUART1 works (38400 baud, takes over swdio pins) - * - Display comm. over SPI, can clear screen - * - Can read buttons through PAL (through interrupts now) - */ - -THD_WORKING_AREA(waThread2, 96); -THD_FUNCTION(Thread2, arg) -{ - (void)arg; - - dogs_init(); - - while (1) { - chThdSleepMilliseconds(100); - dogs_buffer[0] = button_state; - dogs_buffer[1] = button_state; - dogs_buffer[2] = button_state; - dogs_buffer[3] = button_state; - dogs_flush(); - } -} - -THD_TABLE_BEGIN - THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL) -THD_TABLE_END - -int main(void) -{ - halInit(); - chSysInit(); - - buttons_init(); - - // Below code for serial -- note that it cuts off debugging, and MUST be used in a thread - //chThdSleepMilliseconds(2000); - //palSetPadMode(GPIOA, 13, PAL_MODE_ALTERNATE(6)); - //palSetPadMode(GPIOA, 14, PAL_MODE_ALTERNATE(6)); - //sdStart(&LPSD1, NULL); - //chnWrite(&LPSD1, (const uint8_t *)"Hello World!\r\n", 14); - - - - /* This is now the idle thread loop, you may perform here a low priority - task but YOU MUST NEVER TRY TO SLEEP OR WAIT in this loop. Note that - this tasks runs at the lowest priority level so any instruction added - here will be executed after all other tasks have been started. */ - while (1); -} - +/** + * main.c - Firmware entry point and main loop for game or testing. + * Copyright (C) 2020 Clyne Sullivan + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * See the GNU General Public License for more details. + */ + +#include "buttons.h" +#include "ch.h" +#include "dogs.h" +#include "hal.h" + +/* + * Progress: + * - Serial through LPUART1 works (38400 baud, takes over swdio pins) + * - Display comm. over SPI, can clear screen + * - Can read buttons through PAL (through interrupts now) + */ + +THD_WORKING_AREA(waThread2, 96); +THD_FUNCTION(Thread2, arg) +{ + (void)arg; + + dogs_init(); + + const unsigned char testbitmap[] = { + 8, 8, + 0b00111100, + 0b01100110, + 0b01000010, + 0b01111110, + 0b01100110, + 0b01000010, + 0b11000000, + 0b11000000, + }; + + + int x = 0, y = 0; + while (1) { + chThdSleepMilliseconds(100); + + unsigned char b = button_state; + if ((b & (BUTTON_JOYUR | BUTTON_JOYUL)) == (BUTTON_JOYUR | BUTTON_JOYUL)) + y--; + else if ((b & (BUTTON_JOYUR | BUTTON_JOYDR)) == (BUTTON_JOYUR | BUTTON_JOYDR)) + x++; + else if ((b & (BUTTON_JOYDR | BUTTON_JOYDL)) == (BUTTON_JOYDR | BUTTON_JOYDL)) + y++; + else if ((b & (BUTTON_JOYDL | BUTTON_JOYUL)) == (BUTTON_JOYDL | BUTTON_JOYUL)) + x--; + + dogs_clear(); + draw_bitmap(x, y, testbitmap); + dogs_flush(); + } +} + +THD_TABLE_BEGIN + THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL) +THD_TABLE_END + +int main(void) +{ + halInit(); + chSysInit(); + + buttons_init(); + + // Below code for serial -- note that it cuts off debugging, and MUST be used in a thread + //chThdSleepMilliseconds(2000); + //palSetPadMode(GPIOA, 13, PAL_MODE_ALTERNATE(6)); + //palSetPadMode(GPIOA, 14, PAL_MODE_ALTERNATE(6)); + //sdStart(&LPSD1, NULL); + //chnWrite(&LPSD1, (const uint8_t *)"Hello World!\r\n", 14); + + + + /* This is now the idle thread loop, you may perform here a low priority + task but YOU MUST NEVER TRY TO SLEEP OR WAIT in this loop. Note that + this tasks runs at the lowest priority level so any instruction added + here will be executed after all other tasks have been started. */ + while (1); +} + +void HardFault_Handler() +{ + while (1); +} +