summaryrefslogtreecommitdiffstats
path: root/app/adc.c
blob: 8825c71f44e08d16f2575e67ecde1f87850b39f9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include "project.h"


#define POT   GPIO3
#define POT_PORT  GPIOC

#define POT_CHANNEL ADC_CHANNEL13
#define VREF_CHANNEL  ADC_CHANNEL17

#define ADC_TIMEOUT 1000

static enum {
  WAIT_VREF,
  WAIT_POT
} state = WAIT_VREF;


static uint32_t adc_stamp;
static uint16_t pot, vref;

uint8_t pot_brightness = 0x8;


static void start_conversion (uint8_t ch)
{
  adc_stamp = ticks;
  adc_set_regular_sequence (ADC1, 1, &ch);
  adc_start_conversion_regular (ADC1);
}

static void calculate_and_set_brightness (void)
{
  static uint32_t spot, svref;
  uint32_t v;

  /* dumb IIR with 16x gain */
  spot *= 15;
  spot >>= 4;
  spot += pot ;

  svref *= 15;
  svref >>= 4;
  svref += vref  ;


  if (svref > 65535) svref = 65535;

  if (spot > 65535) spot = 65535;

  v = spot << 16;
  v /= svref;
  v <<= 8;
  v /= 12014;  // vref is 1.2v FSD is 3.3v, 15 brightness levels so (65536 * (3.3/1.2) /15 )

  v >>= 8;


  if (v > 15) v = 15;

  pot_brightness = v;
}


void adc_dispatch (void)
{
  uint32_t now = ticks;
  uint32_t ago;

  ago = now - adc_stamp;

  if (ago > ADC_TIMEOUT) {
    adc_power_off (ADC1);
    adc_power_on (ADC1);
    state = WAIT_VREF;
    start_conversion (VREF_CHANNEL);
    return;
  }

  if (!adc_eoc (ADC1))
    return;

  switch (state) {
  case WAIT_VREF:
    vref = adc_read_regular (ADC1);
    start_conversion (POT_CHANNEL);
    state = WAIT_POT;
    break;

  case WAIT_POT:
    pot = adc_read_regular (ADC1);
    start_conversion (VREF_CHANNEL);
    calculate_and_set_brightness();

  /* fall through */
  default:
    state = WAIT_VREF;
  }
}














void adc_init (void)
{
  rcc_periph_clock_enable (RCC_ADC1);

  MAP_ANALOG_INPUT (POT);

  adc_power_off (ADC1);
  adc_disable_scan_mode (ADC1);
  adc_enable_temperature_sensor();

  adc_set_single_conversion_mode (ADC1);
  adc_enable_temperature_sensor(); /*Enables reference*/
  adc_set_sample_time (ADC1, POT_CHANNEL, ADC_SMPR_SMP_480CYC);
  adc_set_sample_time (ADC1, VREF_CHANNEL, ADC_SMPR_SMP_480CYC);
  adc_enable_external_trigger_regular (ADC1, 0, ADC_CR2_EXTEN_DISABLED);
  adc_set_right_aligned (ADC1);
  adc_eoc_after_group (ADC1);

  adc_power_on (ADC1);
  adc_enable_temperature_sensor(); /*Enables reference*/

  state = WAIT_VREF;
  start_conversion (VREF_CHANNEL);
}