]> www.fi.muni.cz Git - bike-lights.git/blob - firmware/ambient.c
pwm.c: channels running - visible from the outside
[bike-lights.git] / firmware / ambient.c
1 #include <avr/io.h>
2 #include <avr/eeprom.h>
3
4 #include "lights.h"
5
6 #define AMBIENT_VAL_SHIFT 2
7 static uint16_t ambient_val;
8 volatile unsigned char ambient_zone;
9 static unsigned char ambient_min, ambient_max;
10
11 /* logging */
12 #define AMBIENT_LOG_SIZE 128
13 static unsigned char ambient_log_offset_stored EEMEM;
14 static unsigned char ambient_log_offset;
15 static unsigned char ambient_log[AMBIENT_LOG_SIZE] EEMEM;
16
17 /* My photodiode reads 0x00C5 .. 0x033B */
18 typedef struct {
19         uint16_t lo, hi;
20 } ambient_zone_t;
21
22 /*
23  * Note: these have to be sorted, starting with 0, ending with 0xFFFF
24  * and having small overlaps in order to provide a bit of hysteresis.
25  */
26 static ambient_zone_t ambient_zones[] = {
27         { 0x0000                   , 0x0280<<AMBIENT_VAL_SHIFT }, // dark
28         { 0x0270<<AMBIENT_VAL_SHIFT, 0x02f0<<AMBIENT_VAL_SHIFT }, // evening
29         { 0x02e8<<AMBIENT_VAL_SHIFT, 0x030a<<AMBIENT_VAL_SHIFT }, // dawn
30         { 0x0308<<AMBIENT_VAL_SHIFT, 0xffff                    }, // day
31 };
32 #define N_AMBIENT_ZONES (sizeof(ambient_zones)/sizeof(ambient_zones[0]))
33
34 void init_ambient()
35 {
36         ambient_val = 0;
37         ambient_max = 0;
38         ambient_min = 0xFF;
39         ambient_zone = 1;
40
41         ambient_log_offset = eeprom_read_byte(&ambient_log_offset_stored);
42
43         if (ambient_log_offset == AMBIENT_LOG_SIZE)
44                 ambient_log_offset = 0; // start over
45 }
46
47 void susp_ambient()
48 {
49         unsigned char stored_offset;
50
51         ambient_log_min_max();
52
53         stored_offset = eeprom_read_byte(&ambient_log_offset_stored);
54         if (stored_offset != ambient_log_offset)
55                 eeprom_write_byte(&ambient_log_offset_stored,
56                         ambient_log_offset);
57 }
58
59 void ambient_log_min_max()
60 {
61         if (ambient_log_offset >= AMBIENT_LOG_SIZE - 1)
62                 return;
63
64         eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_min);
65         eeprom_write_byte(&ambient_log[ambient_log_offset++], ambient_max);
66
67         ambient_min = 0xFF;
68         ambient_max = 0;
69 }
70
71 void ambient_zone_changed()
72 {
73 #if 1
74         log_byte(0xab);
75         log_byte(ambient_zone);
76         log_word(ambient_val);
77         log_flush();
78 #endif
79
80         // led_set_pattern(N_PWMLEDS, status_led_pattern_select());
81         // led_set_pattern(N_PWMLEDS+1, illumination_led_pattern_select());
82         // pattern_reload();
83 }
84
85 void ambient_adc(uint16_t adcval)
86 {
87         unsigned char old_zone = ambient_zone;
88         unsigned char byte_val;
89
90         ambient_val += adcval - (ambient_val
91                 >> (AMBIENT_VAL_SHIFT - AMBIENT_ADC_SHIFT));
92
93         while (ambient_zones[ambient_zone].lo > ambient_val)
94                 ambient_zone--;
95
96         while (ambient_zones[ambient_zone].hi < ambient_val)
97                 ambient_zone++;
98
99         byte_val = adcval >> 2;
100
101         if (ambient_min > byte_val)
102                 ambient_min = byte_val;
103
104         if (ambient_max < byte_val)
105                 ambient_max = byte_val;
106 #if 0
107         if (old_zone != ambient_zone) {
108                 log_byte(0xab);
109                 log_byte(ambient_zone);
110                 log_word(adcval);
111                 log_flush();
112         }
113                 // ambient_zone_changed();
114 #endif
115 }
116