aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClyne Sullivan <clyne@bitgloo.com>2021-09-17 07:26:50 -0400
committerClyne Sullivan <clyne@bitgloo.com>2021-09-17 07:26:50 -0400
commitc61598fe95bb188ca28f1710dd8a42907bb797cb (patch)
tree42be7889b8e873775ef656ddae98cb2e6b5e4b3e
parent6790246c3c731e88094161a594c9c70a3f7903f4 (diff)
use rtc for timing
-rw-r--r--cfg/chconf.h14
-rw-r--r--cfg/halconf.h2
-rw-r--r--cfg/mcuconf.h12
-rw-r--r--dogs.c50
-rw-r--r--main.c153
-rwxr-xr-xopenocd.sh2
6 files changed, 126 insertions, 107 deletions
diff --git a/cfg/chconf.h b/cfg/chconf.h
index dc2ccc1..25d444a 100644
--- a/cfg/chconf.h
+++ b/cfg/chconf.h
@@ -451,11 +451,11 @@
* @note This macro can be used to activate a power saving mode.
*/
#define CH_CFG_IDLE_ENTER_HOOK() { \
- RCC->ICSCR = (RCC->ICSCR & ~RCC_ICSCR_MSIRANGE_Msk); \
- while (!(RCC->CR & RCC_CR_MSIRDY)); \
- PWR->CR &= ~PWR_CR_LPRUN; \
- PWR->CR |= PWR_CR_LPRUN; \
}
+// RCC->ICSCR = (RCC->ICSCR & ~RCC_ICSCR_MSIRANGE_Msk);
+// while (!(RCC->CR & RCC_CR_MSIRDY));
+// PWR->CR &= ~PWR_CR_LPRUN;
+// PWR->CR |= PWR_CR_LPRUN;
/**
* @brief Idle thread leave hook.
@@ -464,10 +464,10 @@
* @note This macro can be used to deactivate a power saving mode.
*/
#define CH_CFG_IDLE_LEAVE_HOOK() { \
- RCC->ICSCR |= 6 << RCC_ICSCR_MSIRANGE_Pos; \
- while (!(RCC->CR & RCC_CR_MSIRDY)); \
- PWR->CR &= ~PWR_CR_LPRUN; \
}
+// RCC->ICSCR |= 6 << RCC_ICSCR_MSIRANGE_Pos;
+// while (!(RCC->CR & RCC_CR_MSIRDY));
+// PWR->CR &= ~PWR_CR_LPRUN;
/**
* @brief System halt hook.
diff --git a/cfg/halconf.h b/cfg/halconf.h
index 5cdb5e0..6688b95 100644
--- a/cfg/halconf.h
+++ b/cfg/halconf.h
@@ -128,7 +128,7 @@
* @brief Enables the RTC subsystem.
*/
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
-#define HAL_USE_RTC FALSE
+#define HAL_USE_RTC TRUE
#endif
/**
diff --git a/cfg/mcuconf.h b/cfg/mcuconf.h
index 217d13f..96e9080 100644
--- a/cfg/mcuconf.h
+++ b/cfg/mcuconf.h
@@ -44,22 +44,22 @@
#define STM32_PLS STM32_PLS_LEV4
#define STM32_HSI16_ENABLED TRUE
#define STM32_HSI16_DIVIDER_ENABLED FALSE
-#define STM32_LSI_ENABLED FALSE
+#define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED FALSE
#define STM32_LSE_ENABLED FALSE
#define STM32_ADC_CLOCK_ENABLED TRUE
#define STM32_MSIRANGE STM32_MSIRANGE_4M
#define STM32_SW STM32_SW_MSI
-#define STM32_PLLSRC STM32_PLLSRC_HSI16
-#define STM32_PLLMUL_VALUE 3
-#define STM32_PLLDIV_VALUE 4
+#define STM32_PLLSRC STM32_PLLSRC_NONE
+#define STM32_PLLMUL_VALUE 1
+#define STM32_PLLDIV_VALUE 8
#define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV1
#define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_MCOPRE STM32_MCOPRE_DIV1
-#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK
-#define STM32_RTCPRE STM32_RTCPRE_DIV2
+#define STM32_RTCSEL STM32_RTCSEL_LSI // ~37kHz
+#define STM32_RTCPRE STM32_RTCPRE_DIV2 // HSE only!
#define STM32_USART2SEL STM32_USART2SEL_APB
#define STM32_LPUART1SEL STM32_LPUART1SEL_APB
#define STM32_I2C1SEL STM32_I2C1SEL_APB
diff --git a/dogs.c b/dogs.c
index a29ee2c..7d32698 100644
--- a/dogs.c
+++ b/dogs.c
@@ -21,6 +21,17 @@ unsigned char dogs_buffer[DISP_WIDTH * DISP_HEIGHT / 8];
static volatile bool dogs_spi_done = false;
+static void spi_send(unsigned char *data, unsigned int len)
+{
+ dogs_spi_done = false;
+ spiStartSend(&SPID1, len, data);
+ while (!dogs_spi_done)
+ asm("wfi");
+
+ //for (; len > 0; --len)
+ // spiPolledExchange(&SPID1, *data++);
+}
+
static void dogs_init_display();
static void dogs_spi_callback(SPIDriver *spid)
{
@@ -54,27 +65,15 @@ void dogs_init()
dogs_flush();
}
-void dogs_write_data(unsigned char byte)
-{
- SET_DATA;
- dogs_spi_done = false;
- spiStartSend(&SPID1, 1, &byte);
- while (!dogs_spi_done);
-}
void dogs_write_cmd(unsigned char byte)
{
- SET_CMD;
- dogs_spi_done = false;
- spiStartSend(&SPID1, 1, &byte);
- while (!dogs_spi_done);
+ spi_send(&byte, 1);
}
void dogs_set_column(unsigned int col)
{
- //if (col < DISP_WIDTH) {
- dogs_write_cmd(0x10 | ((col >> 4) & 0xF));
- dogs_write_cmd(0x00 | (col & 0xF));
- //}
+ dogs_write_cmd(0x10 | ((col >> 4) & 0xF));
+ dogs_write_cmd(0x00 | (col & 0xF));
}
void dogs_set_power(unsigned int bits)
{
@@ -133,6 +132,7 @@ void dogs_set_advanced(unsigned int bits)
void dogs_init_display()
{
+ SET_CMD;
CS_LOW;
dogs_reset();
CS_HIGH;
@@ -154,9 +154,10 @@ void dogs_init_display()
void dogs_clear()
{
- unsigned char *ptr = dogs_buffer;
- int count = sizeof(dogs_buffer);
- for (; count > 8; count -= 8) {
+ uint32_t *ptr = (uint32_t *)dogs_buffer;
+ unsigned int count = sizeof(dogs_buffer) / sizeof(uint32_t) / 12;
+
+ for (; count; --count) {
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
@@ -165,24 +166,25 @@ void dogs_clear()
*ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
- }
- for (; --count >= 0;)
*ptr++ = 0;
+ *ptr++ = 0;
+ *ptr++ = 0;
+ *ptr++ = 0;
+ }
}
void dogs_flush()
{
unsigned char *ptr = dogs_buffer;
CS_LOW;
- for (int page = 0; page < 8; page++) {
+ for (int page = 0; page < 8; ++page) {
+ SET_CMD;
dogs_set_page(page);
dogs_set_column(30);
SET_DATA;
- dogs_spi_done = false;
- spiStartSend(&SPID1, 102, ptr);
+ spi_send(ptr, 102);
ptr += 102;
- while (!dogs_spi_done);
}
CS_HIGH;
}
diff --git a/main.c b/main.c
index 5c963fc..37c1471 100644
--- a/main.c
+++ b/main.c
@@ -29,9 +29,93 @@
* - Run at 4MHz, drop to low-power run/sleep @ 64kHz for idle: 375uA (also lowered contrast)
* - Sleep display for 'pause': ~240uA
*
+ * - Use RTC for delay, Stop mode when idle: 348uA
+ *
* - Flappy bird is going, 2048 next
*/
+static int readVddmv();
+
+THD_WORKING_AREA(waThread2, 128);
+THD_FUNCTION(Thread2, arg)
+{
+ (void)arg;
+
+ dogs_init();
+ flapbird_init();
+}
+THD_TABLE_BEGIN
+ THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL)
+THD_TABLE_END
+
+static void alarm_callback(RTCDriver *rtcp, rtcevent_t event)
+{
+ (void)rtcp;
+ (void)event;
+
+ static bool sleep = false;
+
+ bool sleep_button = (button_state & BUTTON_1) != 0;
+ if (sleep && !sleep_button)
+ return;
+
+ RCC->ICSCR |= 6 << RCC_ICSCR_MSIRANGE_Pos;
+ dogs_set_sleep(false);
+
+ if (sleep_button) {
+ sleep ^= true;
+ if (sleep) {
+ draw_number(DISP_WIDTH - 33, 0,
+ !(PWR->CSR & PWR_CSR_PVDO) ? readVddmv() : 1);
+ dogs_flush();
+ }
+ }
+
+ if (!sleep)
+ flapbird_loop();
+
+ dogs_set_sleep(true);
+}
+
+int main(void)
+{
+ halInit();
+ chSysInit();
+ buttons_init();
+
+ static const RTCWakeup wakeupcfg = {
+ (0 << 16) | // wucksel (37k /16 = ~2k)
+ 240 // wut (hope for 10Hz)
+ };
+ rtcSTM32SetPeriodicWakeup(&RTCD1, &wakeupcfg);
+ rtcSetCallback(&RTCD1, alarm_callback);
+
+ RCC->CR &= ~RCC_CR_HSION;
+ PWR->CR |= PWR_CR_LPSDSR | PWR_CR_ULP;
+ PWR->CR |= PWR_CR_LPRUN;
+ SCB->SCR = 6;
+ FLASH->ACR |= FLASH_ACR_SLEEP_PD;
+
+ // 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)
+ asm("wfe");
+}
+
+void HardFault_Handler()
+{
+ while (1);
+}
+
static volatile bool adc_is_complete = false;
static void adc_callback(ADCDriver *adcd)
{
@@ -55,7 +139,7 @@ static const ADCConversionGroup adcgrpcfg = {
.chselr = ADC_CHSELR_CHSEL17 /* CHSELR */
};
-static int readVddmv()
+int readVddmv()
{
adcsample_t reading = 0;
@@ -74,70 +158,3 @@ static int readVddmv()
return 3000 * /* CAL */ *((adcsample_t *)0x1FF80078) / reading;
}
-
-THD_WORKING_AREA(waThread2, 128);
-THD_FUNCTION(Thread2, arg)
-{
- (void)arg;
-
- dogs_init();
-
- flapbird_init();
-
- bool sleep = false;
- while (1) {
- if (button_state & BUTTON_1) {
- sleep ^= true;
- if (sleep) {
- draw_number(DISP_WIDTH - 33, 0,
- !(PWR->CSR & PWR_CSR_PVDO) ? readVddmv() : 1);
- dogs_flush();
- }
- dogs_set_sleep(sleep);
- }
-
- int dtime = 100;
- if (!sleep) {
- dtime = flapbird_loop();
- }
-
- chThdSleepS(TIME_MS2I(dtime) / 64);
- }
-}
-
-THD_TABLE_BEGIN
- THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL)
-THD_TABLE_END
-
-int main(void)
-{
- halInit();
- chSysInit();
-
- RCC->CR &= ~RCC_CR_HSION;
- PWR->CR |= PWR_CR_LPSDSR;
-
- 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)
- asm("wfi");
-}
-
-void HardFault_Handler()
-{
- while (1);
-}
-
diff --git a/openocd.sh b/openocd.sh
index 6cf8e57..90d4052 100755
--- a/openocd.sh
+++ b/openocd.sh
@@ -1 +1 @@
-sudo openocd -f /usr/local/share/openocd/scripts/interface/cmsis-dap.cfg -f /usr/local/share/openocd/scripts/target/stm32l0.cfg
+sudo openocd -f /usr/local/share/openocd/scripts/interface/stlink-v2.cfg -f /usr/local/share/openocd/scripts/target/stm32l0.cfg