blob: d085d0a59d30cbdc4deb2b6da6cd6381e4b00f5b (
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
|
/*
* CNC-remote-control
* Feed override switch
*
* Copyright (C) 2011-2016 Michael Buesch <m@bues.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "override.h"
#include "util.h"
#include "lcd.h"
#include "main.h"
#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/wdt.h>
#define ADC_HYST 4
#define ADC_MINMAX_DEADBAND 4
#define ADC_REAL_MIN 0
#define ADC_REAL_MAX 0x3FF
#define ADC_MIN (ADC_REAL_MIN + ADC_MINMAX_DEADBAND)
#define ADC_MAX (ADC_REAL_MAX - ADC_MINMAX_DEADBAND)
static uint16_t last_override_adc;
static uint8_t last_override_pos;
static void adc_trigger(bool freerunning)
{
/* Start ADC0 with AVCC reference and a prescaler of 128. */
ADMUX = (1 << REFS0);
ADCSRA = (1 << ADEN) | (0 << ADIE) | (1 << ADSC) |
(freerunning ? (1 << ADATE) : 0) |
(1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2);
}
static inline void adc_busywait(void)
{
do { } while (ADCSRA & (1 << ADSC));
ADCSRA |= (1 << ADIF); /* Clear IRQ flag */
}
void override_init(void)
{
last_override_adc = ADC_REAL_MIN;
last_override_pos = 0;
/* Discard the first measurement */
adc_trigger(0);
adc_busywait();
/* Start the ADC in freerunning mode. */
adc_trigger(1);
}
uint8_t override_get_pos(void)
{
uint16_t adc;
uint8_t pos;
if (!(ADCSRA & (1 << ADIF))) {
/* There was no new conversion */
return last_override_pos;
}
adc = ADC;
ADCSRA |= (1 << ADIF); /* Clear IRQ flag */
if (adc <= ADC_MIN)
adc = ADC_REAL_MIN;
else if (adc >= ADC_MAX)
adc = ADC_REAL_MAX;
else if (abs((int16_t)adc - (int16_t)last_override_adc) <= ADC_HYST)
adc = last_override_adc;
if (adc == last_override_adc)
return last_override_pos;
pos = (uint8_t)(((uint32_t)adc - (uint32_t)ADC_REAL_MIN) * (uint32_t)0xFF /
((uint32_t)ADC_REAL_MAX - (uint32_t)ADC_REAL_MIN));
last_override_adc = adc;
last_override_pos = pos;
return pos;
}
|