diff --git a/build-number.txt b/build-number.txt index d9061d9..6bb2f4e 100644 --- a/build-number.txt +++ b/build-number.txt @@ -1 +1 @@ -375 +389 diff --git a/src/led.c b/src/led.c index bad20ff..537093e 100644 --- a/src/led.c +++ b/src/led.c @@ -3,6 +3,7 @@ LED_Colour_t LED_PixelData[LED_COUNT] = {{0}}; volatile bool LED_FrameFlag = false; +volatile bool LED_SuspendFlag = false; #define LED_ODR_MASK ((1 << PIN_LED_R_0) | (1 << PIN_LED_G_0) \ | (1 << PIN_LED_B_0) | (1 << PIN_LED_R_1) \ @@ -215,6 +216,7 @@ void LED_Init(void) RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // Fill both DMA buffers + LED_QueuePageFlip = false; LED_Commit(); LED_PageFlip(); LED_Commit(); @@ -244,6 +246,39 @@ void LED_Init(void) LED_StartBCM(0); } +void LED_Suspend(void) +{ + LED_SuspendFlag = true; + while(LED_SuspendFlag); + + // Disable timer and DMA channels + TIM3->CR1 = 0x0000; + TIM3->DIER = 0x0000; + TIM3->CNT = 0; + DMA1->IFCR = DMA_IFCR_CTCIF3; + DMA1_Channel3->CCR = 0x0000; + DMA1_Channel4->CCR = 0x0000; + NVIC_DisableIRQ(DMA1_Channel2_3_IRQn); + NVIC_ClearPendingIRQ(DMA1_Channel2_3_IRQn); + + // Deactivate all rows and columns + GPIOA->BSRR = LED_ODR_MASK; + GPIOF->BSRR = (1 << PIN_ROW_DATA); + for(int i = 0; i < LED_ROWS + 1; i++) + { + LED_PulseRowClock(); + } + + // Disable timer and DMA clocks + RCC->AHBENR &= ~RCC_AHBENR_DMA1EN; + RCC->APB1ENR &= ~RCC_APB1ENR_TIM3EN; +} + +void LED_WakeUp(void) +{ + LED_Init(); +} + void DMA1_Channel2_3_IRQHandler(void) { // Interrupt when all bits have been sent @@ -268,6 +303,12 @@ void DMA1_Channel2_3_IRQHandler(void) LED_PulseRowClock(); } + if(LED_SuspendFlag) + { + LED_SuspendFlag = false; + return; + } + // Start sending bits out again. The row offset caused by the shift // register "lagging" one clock cycle behind because RCK and SCK are // connected to the same signal doesn't matter here: we're not paying much diff --git a/src/led.h b/src/led.h index 83833c2..2416ffd 100644 --- a/src/led.h +++ b/src/led.h @@ -27,6 +27,12 @@ extern volatile bool LED_FrameFlag; void LED_InitShiftRegister(void); void LED_Init(void); +// Enter power-saving mode (LEDs off) +void LED_Suspend(void); + +// Leave power-saving mode +void LED_WakeUp(void); + // Display LED_PixelData, starting with the next frame void LED_Commit(void); diff --git a/src/main.c b/src/main.c index 9c10a4a..57c9d0e 100644 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,8 @@ int main(void) LED_InitShiftRegister(); LightSensor_Init(); + bool powered_down = false; + // Delay a bit to make programming easier for(unsigned int i = 0; i < 1000; i++) { @@ -18,6 +20,17 @@ int main(void) __WFI(); LightSensor_Poll(); Animation_Poll(); + + if(LightSensor_RelativeBrightness == 0 && !powered_down) + { + LED_Suspend(); + powered_down = true; + } + if(powered_down && LightSensor_RelativeBrightness > 0) + { + LED_WakeUp(); + powered_down = false; + } } return 0; diff --git a/src/main.h b/src/main.h index 3b978d4..20c8393 100644 --- a/src/main.h +++ b/src/main.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "stm32f030x6.h" #include "buildid.h"