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