REGION_ALIAS("BSS_RAM", ram0);\r
\r
/* RAM region to be used for the default heap.*/\r
+/* tcsullivan: Set to ram1 so bss reports actual size used. */\r
REGION_ALIAS("HEAP_RAM", ram1);\r
\r
/* Generic rules inclusion.*/\r
#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();
* @brief Enables the SERIAL subsystem.\r
*/\r
#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__)\r
-#define HAL_USE_SERIAL TRUE\r
+#define HAL_USE_SERIAL FALSE\r
#endif\r
\r
/**\r
* @note Disabling this option saves both code and data space.\r
*/\r
#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)\r
-#define ADC_USE_WAIT TRUE\r
+#define ADC_USE_WAIT FALSE\r
#endif\r
\r
/**\r
* @note Disabling this option saves both code and data space.\r
*/\r
#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)\r
-#define ADC_USE_MUTUAL_EXCLUSION TRUE\r
+#define ADC_USE_MUTUAL_EXCLUSION FALSE\r
#endif\r
\r
/*===========================================================================*/\r
* @note Disabling this option saves both code and data space.\r
*/\r
#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__)\r
-#define SPI_USE_WAIT TRUE\r
+#define SPI_USE_WAIT FALSE\r
#endif\r
\r
/**\r
* @note Disabling this option saves both code and data space.\r
*/\r
#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)\r
-#define SPI_USE_MUTUAL_EXCLUSION TRUE\r
+#define SPI_USE_MUTUAL_EXCLUSION FALSE\r
#endif\r
\r
/**\r
* SERIAL driver system settings.\r
*/\r
#define STM32_SERIAL_USE_USART2 FALSE\r
-#define STM32_SERIAL_USE_LPUART1 TRUE\r
+#define STM32_SERIAL_USE_LPUART1 FALSE\r
\r
/*\r
* SPI driver system settings.\r
#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()
{
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)
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()
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;
+ }
+ }
+ }
+}
+
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_
-/**\r
- * main.c - Firmware entry point and main loop for game or testing.\r
- * Copyright (C) 2020 Clyne Sullivan\r
- *\r
- * This program is free software: you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation, either version 3 of the License, or\r
- * (at your option) any later version.\r
- * See the GNU General Public License for more details.\r
- */\r
-\r
-#include "buttons.h"\r
-#include "ch.h"\r
-#include "dogs.h"\r
-#include "hal.h"\r
-\r
-/*\r
- * Progress:\r
- * - Serial through LPUART1 works (38400 baud, takes over swdio pins)\r
- * - Display comm. over SPI, can clear screen\r
- * - Can read buttons through PAL (through interrupts now)\r
- */\r
-\r
-THD_WORKING_AREA(waThread2, 96);\r
-THD_FUNCTION(Thread2, arg)\r
-{\r
- (void)arg;\r
-\r
- dogs_init();\r
-\r
- while (1) {\r
- chThdSleepMilliseconds(100);\r
- dogs_buffer[0] = button_state;\r
- dogs_buffer[1] = button_state;\r
- dogs_buffer[2] = button_state;\r
- dogs_buffer[3] = button_state;\r
- dogs_flush();\r
- }\r
-}\r
-\r
-THD_TABLE_BEGIN\r
- THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL)\r
-THD_TABLE_END\r
-\r
-int main(void)\r
-{\r
- halInit();\r
- chSysInit();\r
-\r
- buttons_init();\r
-\r
- // Below code for serial -- note that it cuts off debugging, and MUST be used in a thread\r
- //chThdSleepMilliseconds(2000);\r
- //palSetPadMode(GPIOA, 13, PAL_MODE_ALTERNATE(6));\r
- //palSetPadMode(GPIOA, 14, PAL_MODE_ALTERNATE(6));\r
- //sdStart(&LPSD1, NULL);\r
- //chnWrite(&LPSD1, (const uint8_t *)"Hello World!\r\n", 14);\r
-\r
-\r
-\r
- /* This is now the idle thread loop, you may perform here a low priority\r
- task but YOU MUST NEVER TRY TO SLEEP OR WAIT in this loop. Note that\r
- this tasks runs at the lowest priority level so any instruction added\r
- here will be executed after all other tasks have been started. */\r
- while (1);\r
-}\r
-\r
+/**
+ * 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);
+}
+