use rtc for timing

master
Clyne 3 years ago
parent 6790246c3c
commit c61598fe95

@ -451,11 +451,11 @@
* @note This macro can be used to activate a power saving mode. * @note This macro can be used to activate a power saving mode.
*/ */
#define CH_CFG_IDLE_ENTER_HOOK() { \ #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. * @brief Idle thread leave hook.
@ -464,10 +464,10 @@
* @note This macro can be used to deactivate a power saving mode. * @note This macro can be used to deactivate a power saving mode.
*/ */
#define CH_CFG_IDLE_LEAVE_HOOK() { \ #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. * @brief System halt hook.

@ -128,7 +128,7 @@
* @brief Enables the RTC subsystem. * @brief Enables the RTC subsystem.
*/ */
#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) #if !defined(HAL_USE_RTC) || defined(__DOXYGEN__)
#define HAL_USE_RTC FALSE #define HAL_USE_RTC TRUE
#endif #endif
/** /**

@ -44,22 +44,22 @@
#define STM32_PLS STM32_PLS_LEV4 #define STM32_PLS STM32_PLS_LEV4
#define STM32_HSI16_ENABLED TRUE #define STM32_HSI16_ENABLED TRUE
#define STM32_HSI16_DIVIDER_ENABLED FALSE #define STM32_HSI16_DIVIDER_ENABLED FALSE
#define STM32_LSI_ENABLED FALSE #define STM32_LSI_ENABLED TRUE
#define STM32_HSE_ENABLED FALSE #define STM32_HSE_ENABLED FALSE
#define STM32_LSE_ENABLED FALSE #define STM32_LSE_ENABLED FALSE
#define STM32_ADC_CLOCK_ENABLED TRUE #define STM32_ADC_CLOCK_ENABLED TRUE
#define STM32_MSIRANGE STM32_MSIRANGE_4M #define STM32_MSIRANGE STM32_MSIRANGE_4M
#define STM32_SW STM32_SW_MSI #define STM32_SW STM32_SW_MSI
#define STM32_PLLSRC STM32_PLLSRC_HSI16 #define STM32_PLLSRC STM32_PLLSRC_NONE
#define STM32_PLLMUL_VALUE 3 #define STM32_PLLMUL_VALUE 1
#define STM32_PLLDIV_VALUE 4 #define STM32_PLLDIV_VALUE 8
#define STM32_HPRE STM32_HPRE_DIV1 #define STM32_HPRE STM32_HPRE_DIV1
#define STM32_PPRE1 STM32_PPRE1_DIV1 #define STM32_PPRE1 STM32_PPRE1_DIV1
#define STM32_PPRE2 STM32_PPRE2_DIV1 #define STM32_PPRE2 STM32_PPRE2_DIV1
#define STM32_MCOSEL STM32_MCOSEL_NOCLOCK #define STM32_MCOSEL STM32_MCOSEL_NOCLOCK
#define STM32_MCOPRE STM32_MCOPRE_DIV1 #define STM32_MCOPRE STM32_MCOPRE_DIV1
#define STM32_RTCSEL STM32_RTCSEL_NOCLOCK #define STM32_RTCSEL STM32_RTCSEL_LSI // ~37kHz
#define STM32_RTCPRE STM32_RTCPRE_DIV2 #define STM32_RTCPRE STM32_RTCPRE_DIV2 // HSE only!
#define STM32_USART2SEL STM32_USART2SEL_APB #define STM32_USART2SEL STM32_USART2SEL_APB
#define STM32_LPUART1SEL STM32_LPUART1SEL_APB #define STM32_LPUART1SEL STM32_LPUART1SEL_APB
#define STM32_I2C1SEL STM32_I2C1SEL_APB #define STM32_I2C1SEL STM32_I2C1SEL_APB

@ -21,6 +21,17 @@ unsigned char dogs_buffer[DISP_WIDTH * DISP_HEIGHT / 8];
static volatile bool dogs_spi_done = false; 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_init_display();
static void dogs_spi_callback(SPIDriver *spid) static void dogs_spi_callback(SPIDriver *spid)
{ {
@ -54,27 +65,15 @@ void dogs_init()
dogs_flush(); 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) void dogs_write_cmd(unsigned char byte)
{ {
SET_CMD; spi_send(&byte, 1);
dogs_spi_done = false;
spiStartSend(&SPID1, 1, &byte);
while (!dogs_spi_done);
} }
void dogs_set_column(unsigned int col) void dogs_set_column(unsigned int col)
{ {
//if (col < DISP_WIDTH) {
dogs_write_cmd(0x10 | ((col >> 4) & 0xF)); dogs_write_cmd(0x10 | ((col >> 4) & 0xF));
dogs_write_cmd(0x00 | (col & 0xF)); dogs_write_cmd(0x00 | (col & 0xF));
//}
} }
void dogs_set_power(unsigned int bits) void dogs_set_power(unsigned int bits)
{ {
@ -133,6 +132,7 @@ void dogs_set_advanced(unsigned int bits)
void dogs_init_display() void dogs_init_display()
{ {
SET_CMD;
CS_LOW; CS_LOW;
dogs_reset(); dogs_reset();
CS_HIGH; CS_HIGH;
@ -154,9 +154,11 @@ void dogs_init_display()
void dogs_clear() void dogs_clear()
{ {
unsigned char *ptr = dogs_buffer; uint32_t *ptr = (uint32_t *)dogs_buffer;
int count = sizeof(dogs_buffer); unsigned int count = sizeof(dogs_buffer) / sizeof(uint32_t) / 12;
for (; count > 8; count -= 8) {
for (; count; --count) {
*ptr++ = 0;
*ptr++ = 0; *ptr++ = 0;
*ptr++ = 0; *ptr++ = 0;
*ptr++ = 0; *ptr++ = 0;
@ -165,24 +167,24 @@ void dogs_clear()
*ptr++ = 0; *ptr++ = 0;
*ptr++ = 0; *ptr++ = 0;
*ptr++ = 0; *ptr++ = 0;
}
for (; --count >= 0;)
*ptr++ = 0; *ptr++ = 0;
*ptr++ = 0;
*ptr++ = 0;
}
} }
void dogs_flush() void dogs_flush()
{ {
unsigned char *ptr = dogs_buffer; unsigned char *ptr = dogs_buffer;
CS_LOW; CS_LOW;
for (int page = 0; page < 8; page++) { for (int page = 0; page < 8; ++page) {
SET_CMD;
dogs_set_page(page); dogs_set_page(page);
dogs_set_column(30); dogs_set_column(30);
SET_DATA; SET_DATA;
dogs_spi_done = false; spi_send(ptr, 102);
spiStartSend(&SPID1, 102, ptr);
ptr += 102; ptr += 102;
while (!dogs_spi_done);
} }
CS_HIGH; CS_HIGH;
} }

143
main.c

@ -29,51 +29,12 @@
* - Run at 4MHz, drop to low-power run/sleep @ 64kHz for idle: 375uA (also lowered contrast) * - Run at 4MHz, drop to low-power run/sleep @ 64kHz for idle: 375uA (also lowered contrast)
* - Sleep display for 'pause': ~240uA * - Sleep display for 'pause': ~240uA
* *
* - Use RTC for delay, Stop mode when idle: 348uA
*
* - Flappy bird is going, 2048 next * - Flappy bird is going, 2048 next
*/ */
static volatile bool adc_is_complete = false; static int readVddmv();
static void adc_callback(ADCDriver *adcd)
{
(void)adcd;
adc_is_complete = true;
}
static const ADCConfig adccfg = {
.dummy = 0
};
static const ADCConversionGroup adcgrpcfg = {
.circular = false,
.num_channels = 1,
.end_cb = adc_callback,
.error_cb = NULL,
.cfgr1 = ADC_CFGR1_RES_12BIT, /* CFGR1 */
.cfgr2 = 0, /* CFGR2 */
.tr = ADC_TR(0, 0), /* TR */
.smpr = ADC_SMPR_SMP_1P5, /* SMPR */
.chselr = ADC_CHSELR_CHSEL17 /* CHSELR */
};
static int readVddmv()
{
adcsample_t reading = 0;
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY));
adcStart(&ADCD1, &adccfg);
adcSTM32EnableVREF(&ADCD1);
adcStartConversion(&ADCD1, &adcgrpcfg, &reading, 1);
while (!adc_is_complete);
adcStopConversion(&ADCD1);
adcSTM32DisableVREF(&ADCD1);
adcStop(&ADCD1);
RCC->CR &= ~RCC_CR_HSION;
return 3000 * /* CAL */ *((adcsample_t *)0x1FF80078) / reading;
}
THD_WORKING_AREA(waThread2, 128); THD_WORKING_AREA(waThread2, 128);
THD_FUNCTION(Thread2, arg) THD_FUNCTION(Thread2, arg)
@ -81,43 +42,59 @@ THD_FUNCTION(Thread2, arg)
(void)arg; (void)arg;
dogs_init(); dogs_init();
flapbird_init(); flapbird_init();
}
THD_TABLE_BEGIN
THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL)
THD_TABLE_END
bool sleep = false; static void alarm_callback(RTCDriver *rtcp, rtcevent_t event)
while (1) { {
if (button_state & BUTTON_1) { (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; sleep ^= true;
if (sleep) { if (sleep) {
draw_number(DISP_WIDTH - 33, 0, draw_number(DISP_WIDTH - 33, 0,
!(PWR->CSR & PWR_CSR_PVDO) ? readVddmv() : 1); !(PWR->CSR & PWR_CSR_PVDO) ? readVddmv() : 1);
dogs_flush(); dogs_flush();
} }
dogs_set_sleep(sleep);
} }
int dtime = 100; if (!sleep)
if (!sleep) { flapbird_loop();
dtime = flapbird_loop();
}
chThdSleepS(TIME_MS2I(dtime) / 64); dogs_set_sleep(true);
}
} }
THD_TABLE_BEGIN
THD_TABLE_THREAD(0, "game", waThread2, Thread2, NULL)
THD_TABLE_END
int main(void) int main(void)
{ {
halInit(); halInit();
chSysInit(); chSysInit();
buttons_init();
RCC->CR &= ~RCC_CR_HSION; static const RTCWakeup wakeupcfg = {
PWR->CR |= PWR_CR_LPSDSR; (0 << 16) | // wucksel (37k /16 = ~2k)
240 // wut (hope for 10Hz)
};
rtcSTM32SetPeriodicWakeup(&RTCD1, &wakeupcfg);
rtcSetCallback(&RTCD1, alarm_callback);
buttons_init(); 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 // Below code for serial -- note that it cuts off debugging, and MUST be used in a thread
//chThdSleepMilliseconds(2000); //chThdSleepMilliseconds(2000);
@ -126,14 +103,12 @@ int main(void)
//sdStart(&LPSD1, NULL); //sdStart(&LPSD1, NULL);
//chnWrite(&LPSD1, (const uint8_t *)"Hello World!\r\n", 14); //chnWrite(&LPSD1, (const uint8_t *)"Hello World!\r\n", 14);
/* This is now the idle thread loop, you may perform here a low priority /* 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 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 this tasks runs at the lowest priority level so any instruction added
here will be executed after all other tasks have been started. */ here will be executed after all other tasks have been started. */
while (1) while (1)
asm("wfi"); asm("wfe");
} }
void HardFault_Handler() void HardFault_Handler()
@ -141,3 +116,45 @@ void HardFault_Handler()
while (1); while (1);
} }
static volatile bool adc_is_complete = false;
static void adc_callback(ADCDriver *adcd)
{
(void)adcd;
adc_is_complete = true;
}
static const ADCConfig adccfg = {
.dummy = 0
};
static const ADCConversionGroup adcgrpcfg = {
.circular = false,
.num_channels = 1,
.end_cb = adc_callback,
.error_cb = NULL,
.cfgr1 = ADC_CFGR1_RES_12BIT, /* CFGR1 */
.cfgr2 = 0, /* CFGR2 */
.tr = ADC_TR(0, 0), /* TR */
.smpr = ADC_SMPR_SMP_1P5, /* SMPR */
.chselr = ADC_CHSELR_CHSEL17 /* CHSELR */
};
int readVddmv()
{
adcsample_t reading = 0;
RCC->CR |= RCC_CR_HSION;
while (!(RCC->CR & RCC_CR_HSIRDY));
adcStart(&ADCD1, &adccfg);
adcSTM32EnableVREF(&ADCD1);
adcStartConversion(&ADCD1, &adcgrpcfg, &reading, 1);
while (!adc_is_complete);
adcStopConversion(&ADCD1);
adcSTM32DisableVREF(&ADCD1);
adcStop(&ADCD1);
RCC->CR &= ~RCC_CR_HSION;
return 3000 * /* CAL */ *((adcsample_t *)0x1FF80078) / reading;
}

@ -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

Loading…
Cancel
Save