added light level setting based on ambient light detection
this required increasing the main interrupt rate again. need to actually test during the daytime to see if it works ok. it's a little bit jumpy when it's dark but oh well, that's fine.
This commit is contained in:
parent
83fb171fbf
commit
a6966fc32f
|
@ -56,28 +56,24 @@ volatile uint32_t uptime;
|
|||
|
||||
void SysTick_Handler(void)
|
||||
{
|
||||
if (++ticnt > 0x1ff) {
|
||||
if (++ticnt > 0x3ff) {
|
||||
ticnt = 0;
|
||||
uptime++;
|
||||
}
|
||||
|
||||
// all processes update at 1/128 duty
|
||||
switch (ticnt & 0x3) {
|
||||
// light sensor updates at ~1ms
|
||||
adc_process_lsens();
|
||||
|
||||
// general processes update at 1/128 duty
|
||||
switch (ticnt & 0x7) {
|
||||
case 0: { // send new LEDs
|
||||
led_rgb_update();
|
||||
led_matrix_send();
|
||||
break;
|
||||
}
|
||||
case 1: { // process / initialize light sensor
|
||||
adc_process_lsens(0);
|
||||
break;
|
||||
}
|
||||
case 2: { // convert light sensor
|
||||
adc_process_lsens(1);
|
||||
break;
|
||||
}
|
||||
case 3: { // process buttons
|
||||
case 1: { // process buttons
|
||||
btn_poll();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
void systick_init(void)
|
||||
{
|
||||
SysTick->CMP = (SystemCoreClock / 512) - 1; // we want a 512Hz interrupt
|
||||
SysTick->CMP = (SystemCoreClock / 1024) - 1; // we want a 1024Hz interrupt
|
||||
SysTick->CNT = 0; // clear counter
|
||||
SysTick->CTLR = 0xF; // start counter in /1 mode, enable interrupts, auto-reset counter
|
||||
SysTick->SR = 0; // clear count comparison flag
|
||||
|
@ -123,6 +123,9 @@ int main(void)
|
|||
lis2dw_init(); // looking at badge: Y+ up, X+ right, Z+ in front of badge
|
||||
led_init(); // configure matrix IC as well as RGB PWM
|
||||
|
||||
// by default, top LED is in light sense mode
|
||||
adc_set_mode_lsens(LSENS_READING_IDLE);
|
||||
|
||||
// configure random
|
||||
tinymt32_init(&tinymt32_s, DBGMCU_GetCHIPID() | userconf.checksum);
|
||||
|
||||
|
|
|
@ -18,8 +18,12 @@ static GPIO_InitTypeDef lsens_gpio = {
|
|||
};
|
||||
|
||||
uint16_t lsens_val;
|
||||
|
||||
static uint8_t lsens_mode = LSENS_READING_IDLE;
|
||||
|
||||
uint8_t lsens_wait;
|
||||
uint8_t lsens_coarse = 1;
|
||||
|
||||
|
||||
|
||||
void adc_init()
|
||||
|
@ -48,19 +52,16 @@ void adc_convert()
|
|||
|
||||
void adc_read()
|
||||
{
|
||||
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
|
||||
lsens_val = ADC_GetConversionValue(ADC1);
|
||||
uint16_t timeout = 0xfff;
|
||||
while((!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)) && timeout) timeout--;
|
||||
if (timeout) {
|
||||
lsens_val = ADC_GetConversionValue(ADC1);
|
||||
}
|
||||
}
|
||||
|
||||
void adc_set_mode_lsens(uint8_t mode)
|
||||
{
|
||||
lsens_mode = mode;
|
||||
|
||||
// always reconfigure the pins as outputs when calling this
|
||||
lsens_gpio.GPIO_Pin = LSENS_A_PIN | LSENS_K_PIN;
|
||||
lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
GPIO_Init(LSENS_PORT, &lsens_gpio);
|
||||
|
||||
}
|
||||
|
||||
uint8_t adc_get_mode_lsens()
|
||||
|
@ -89,15 +90,70 @@ static void lsens_start()
|
|||
GPIO_Init(LSENS_PORT, &lsens_gpio);
|
||||
}
|
||||
|
||||
static void lsens_end()
|
||||
static void lsens_stop()
|
||||
{
|
||||
adc_set_mode_lsens(LSENS_READING_IDLE);
|
||||
lsens_gpio.GPIO_Pin = LSENS_A_PIN | LSENS_K_PIN;
|
||||
lsens_gpio.GPIO_Mode = GPIO_Mode_Out_PP;
|
||||
GPIO_Init(LSENS_PORT, &lsens_gpio);
|
||||
|
||||
lsens_mode = LSENS_READING_IDLE;
|
||||
}
|
||||
|
||||
void adc_process_lsens(uint8_t convert)
|
||||
void adc_process_lsens()
|
||||
{
|
||||
if (lsens_mode != LSENS_OUTPUT) {
|
||||
// do what needs to be done by me to defeat the light enemys
|
||||
switch (lsens_mode) {
|
||||
case LSENS_READING_IDLE: {
|
||||
// prepare LED, wait a little bit
|
||||
lsens_start();
|
||||
adc_convert();
|
||||
lsens_wait = lsens_coarse;
|
||||
|
||||
lsens_mode = LSENS_READING_START;
|
||||
|
||||
break;
|
||||
}
|
||||
case LSENS_READING_START: {
|
||||
if (!lsens_wait) {
|
||||
// convert the LED
|
||||
adc_convert();
|
||||
|
||||
lsens_mode = LSENS_READING_WAIT;
|
||||
}
|
||||
|
||||
lsens_wait--;
|
||||
|
||||
break;
|
||||
}
|
||||
case LSENS_READING_WAIT: {
|
||||
// read the light sensor value
|
||||
adc_read();
|
||||
lsens_stop();
|
||||
|
||||
// calculate adjustments
|
||||
if (lsens_val > LSENS_COARSE_UP) {
|
||||
lsens_coarse++;
|
||||
if (lsens_coarse > 0x7f) lsens_coarse = 0x7f;
|
||||
} else if (lsens_val < LSENS_COARSE_DOWN) {
|
||||
if (lsens_coarse) lsens_coarse--;
|
||||
}
|
||||
|
||||
lsens_wait = 255 - lsens_coarse;
|
||||
|
||||
// wait a bit before doing it again
|
||||
lsens_mode = LSENS_READING_TIMEOUT;
|
||||
|
||||
break;
|
||||
}
|
||||
case LSENS_READING_TIMEOUT: {
|
||||
if (!lsens_wait) {
|
||||
// do it all again
|
||||
lsens_mode = LSENS_READING_IDLE;
|
||||
}
|
||||
lsens_wait--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,3 +161,8 @@ uint16_t adc_get_lsens()
|
|||
{
|
||||
return lsens_val;
|
||||
}
|
||||
|
||||
uint8_t adc_get_lsens_coarse()
|
||||
{
|
||||
return lsens_coarse;
|
||||
}
|
||||
|
|
|
@ -10,17 +10,21 @@
|
|||
|
||||
|
||||
|
||||
#define LSENS_DARK_THRESHOLD 0x7ff // baseline minimum value reading achieved in darkness
|
||||
#define LSENS_DARK_THRESHOLD 0x7ff // baseline minimum value reading achieved in darkness
|
||||
|
||||
#define LSENS_PORT GPIOA
|
||||
#define LSENS_A_PIN GPIO_Pin_2
|
||||
#define LSENS_K_PIN GPIO_Pin_3
|
||||
#define LSENS_ADC_CH ADC_Channel_3
|
||||
|
||||
enum {
|
||||
#define LSENS_COARSE_UP 0x680 // counts higher than this increase lsens_coarse, maximum 64
|
||||
#define LSENS_COARSE_DOWN 0x580 // counts lower than this decrease lsens_coarse, minimum 1
|
||||
|
||||
enum lsens_mode {
|
||||
LSENS_READING_IDLE = 0,
|
||||
LSENS_READING_START,
|
||||
LSENS_READING_WAIT,
|
||||
LSENS_READING_TIMEOUT,
|
||||
LSENS_OUTPUT = 0xff
|
||||
};
|
||||
|
||||
|
@ -34,7 +38,10 @@ void adc_read();
|
|||
void adc_set_mode_lsens(uint8_t mode);
|
||||
uint8_t adc_get_mode_lsens();
|
||||
|
||||
void adc_process_lsens(uint8_t convert);
|
||||
void adc_process_lsens();
|
||||
|
||||
uint16_t adc_get_lsens();
|
||||
uint8_t adc_get_lsens_coarse();
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "adc.h"
|
||||
#include "btn.h"
|
||||
#include "led.h"
|
||||
#include "ledprog_pep.h"
|
||||
|
@ -22,6 +23,15 @@
|
|||
|
||||
|
||||
|
||||
static const uint8_t led_gc_map[] = {
|
||||
48, 40, 34, 32, // 0 = maybe outside, or really bright inside. 1-3 = indoors
|
||||
30, 28, 27, 25, // 4-7 = indoors
|
||||
23, 21, 19, 18, // 8-11 = indoors normal
|
||||
17, 16, 15, 13, // 12 = dimmest normal, 13 = darker, 14-15 darker still
|
||||
11, 9, 7, 5, // 16-19 = from night room light to computer light
|
||||
0 // 20 = outside mode turns off the LEDs
|
||||
};
|
||||
|
||||
static uint8_t mode = MODE_RUN;
|
||||
static uint8_t tick = 0;
|
||||
|
||||
|
@ -64,6 +74,8 @@ volatile uint8_t prog_run = 5;
|
|||
|
||||
void ui_render()
|
||||
{
|
||||
uint8_t w;
|
||||
|
||||
tick++;
|
||||
|
||||
switch (mode) {
|
||||
|
@ -80,6 +92,19 @@ void ui_render()
|
|||
}
|
||||
}
|
||||
|
||||
// set LED current based on brightness
|
||||
w = adc_get_lsens_coarse();
|
||||
if (w > 19) w = 19;
|
||||
if (!w) {
|
||||
// are you outside? why? it's too fucking hot
|
||||
// we'll shut down when in the presence of big nuclear fire
|
||||
if (adc_get_lsens() < 400) {
|
||||
// yup, outside or in a spotlight at 3ft away or something
|
||||
w = 20;
|
||||
}
|
||||
}
|
||||
is31fl3729_set_global_current(FL3729_ADDR, led_gc_map[w]);
|
||||
|
||||
// temporary: testing
|
||||
|
||||
ledprog_pep[prog_run](tick);
|
||||
|
|
Loading…
Reference in New Issue