|
@@ -22,11 +22,6 @@
|
22
|
22
|
|
23
|
23
|
#include "../../inc/MarlinConfig.h"
|
24
|
24
|
|
25
|
|
-extern "C" {
|
26
|
|
- //#include <lpc17xx_adc.h>
|
27
|
|
- //#include <lpc17xx_pinsel.h>
|
28
|
|
-}
|
29
|
|
-
|
30
|
25
|
HalSerial usb_serial;
|
31
|
26
|
|
32
|
27
|
//u8glib required fucntions
|
|
@@ -112,7 +107,6 @@ void HAL_adc_enable_channel(int ch) {
|
112
|
107
|
};
|
113
|
108
|
}
|
114
|
109
|
|
115
|
|
-uint8_t active_adc = 0;
|
116
|
110
|
void HAL_adc_start_conversion(const uint8_t ch) {
|
117
|
111
|
if (analogInputToDigitalPin(ch) == -1) {
|
118
|
112
|
MYSERIAL.printf("HAL: HAL_adc_start_conversion: invalid channel %d\n", ch);
|
|
@@ -122,7 +116,6 @@ void HAL_adc_start_conversion(const uint8_t ch) {
|
122
|
116
|
LPC_ADC->ADCR &= ~0xFF; // Reset
|
123
|
117
|
SBI(LPC_ADC->ADCR, ch); // Select Channel
|
124
|
118
|
SBI(LPC_ADC->ADCR, 24); // Start conversion
|
125
|
|
- active_adc = ch;
|
126
|
119
|
}
|
127
|
120
|
|
128
|
121
|
bool HAL_adc_finished(void) {
|
|
@@ -130,44 +123,131 @@ bool HAL_adc_finished(void) {
|
130
|
123
|
}
|
131
|
124
|
|
132
|
125
|
// possible config options if something similar is extended to more platforms.
|
133
|
|
-#define ADC_USE_MEDIAN_FILTER // filter out erroneous readings
|
134
|
|
-#define ADC_USE_LOWPASS_FILTER // filter out high frequency noise
|
135
|
|
-#define ADC_LOWPASS_K_VALUE 4 // how much to smooth out noise (1:8)
|
|
126
|
+#define ADC_USE_MEDIAN_FILTER // Filter out erroneous readings
|
|
127
|
+#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
|
|
128
|
+ // (ADC_MEDIAN_FILTER_SIZE + 1) / 2 sample step delay (12 samples @ 500Hz: 24ms phase shift)
|
|
129
|
+ // Memory usage per ADC channel (bytes): (6 * ADC_MEDIAN_FILTER_SIZE) + 16
|
|
130
|
+ // 8 * ((6 * 23) + 16 ) = 1232 Bytes for 8 channels
|
|
131
|
+
|
|
132
|
+#define ADC_USE_LOWPASS_FILTER // Filter out high frequency noise
|
|
133
|
+#define ADC_LOWPASS_K_VALUE (6) // Higher values increase rise time
|
|
134
|
+ // Rise time sample delays for 100% signal convergence on full range step
|
|
135
|
+ // (1 : 13, 2 : 32, 3 : 67, 4 : 139, 5 : 281, 6 : 565, 7 : 1135, 8 : 2273)
|
|
136
|
+ // K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
|
|
137
|
+ // Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
|
|
138
|
+
|
136
|
139
|
|
|
140
|
+// Sourced from https://embeddedgurus.com/stack-overflow/tag/median-filter/
|
137
|
141
|
struct MedianFilter {
|
138
|
|
- uint16_t values[3];
|
139
|
|
- uint8_t next_val;
|
140
|
|
- MedianFilter() {
|
141
|
|
- next_val = 0;
|
142
|
|
- values[0] = values[1] = values[2] = 0;
|
|
142
|
+ #define STOPPER 0 // Smaller than any datum
|
|
143
|
+ struct Pair {
|
|
144
|
+ Pair *point; // Pointers forming list linked in sorted order
|
|
145
|
+ uint16_t value; // Values to sort
|
|
146
|
+ };
|
|
147
|
+
|
|
148
|
+ Pair buffer[ADC_MEDIAN_FILTER_SIZE] = {}; // Buffer of nwidth pairs
|
|
149
|
+ Pair *datpoint = buffer; // Pointer into circular buffer of data
|
|
150
|
+ Pair small = {NULL, STOPPER}; // Chain stopper
|
|
151
|
+ Pair big = {&small, 0}; // Pointer to head (largest) of linked list.
|
|
152
|
+
|
|
153
|
+ uint16_t update(uint16_t datum) {
|
|
154
|
+ Pair *successor; // Pointer to successor of replaced data item
|
|
155
|
+ Pair *scan; // Pointer used to scan down the sorted list
|
|
156
|
+ Pair *scanold; // Previous value of scan
|
|
157
|
+ Pair *median; // Pointer to median
|
|
158
|
+ uint16_t i;
|
|
159
|
+
|
|
160
|
+ if (datum == STOPPER) {
|
|
161
|
+ datum = STOPPER + 1; // No stoppers allowed.
|
|
162
|
+ }
|
|
163
|
+
|
|
164
|
+ if ( (++datpoint - buffer) >= ADC_MEDIAN_FILTER_SIZE) {
|
|
165
|
+ datpoint = buffer; // Increment and wrap data in pointer.
|
|
166
|
+ }
|
|
167
|
+
|
|
168
|
+ datpoint->value = datum; // Copy in new datum
|
|
169
|
+ successor = datpoint->point; // Save pointer to old value's successor
|
|
170
|
+ median = &big; // Median initially to first in chain
|
|
171
|
+ scanold = NULL; // Scanold initially null.
|
|
172
|
+ scan = &big; // Points to pointer to first (largest) datum in chain
|
|
173
|
+
|
|
174
|
+ // Handle chain-out of first item in chain as special case
|
|
175
|
+ if (scan->point == datpoint) {
|
|
176
|
+ scan->point = successor;
|
|
177
|
+ }
|
|
178
|
+ scanold = scan; // Save this pointer and
|
|
179
|
+ scan = scan->point ; // step down chain
|
|
180
|
+
|
|
181
|
+ // Loop through the chain, normal loop exit via break.
|
|
182
|
+ for (i = 0 ; i < ADC_MEDIAN_FILTER_SIZE; ++i) {
|
|
183
|
+ // Handle odd-numbered item in chain
|
|
184
|
+ if (scan->point == datpoint) {
|
|
185
|
+ scan->point = successor; // Chain out the old datum
|
|
186
|
+ }
|
|
187
|
+
|
|
188
|
+ if (scan->value < datum) { // If datum is larger than scanned value
|
|
189
|
+ datpoint->point = scanold->point; // Chain it in here
|
|
190
|
+ scanold->point = datpoint; // Mark it chained in
|
|
191
|
+ datum = STOPPER;
|
|
192
|
+ }
|
|
193
|
+
|
|
194
|
+ // Step median pointer down chain after doing odd-numbered element
|
|
195
|
+ median = median->point; // Step median pointer
|
|
196
|
+ if (scan == &small) {
|
|
197
|
+ break; // Break at end of chain
|
|
198
|
+ }
|
|
199
|
+ scanold = scan; // Save this pointer and
|
|
200
|
+ scan = scan->point; // step down chain
|
|
201
|
+
|
|
202
|
+ // Handle even-numbered item in chain.
|
|
203
|
+ if (scan->point == datpoint) {
|
|
204
|
+ scan->point = successor;
|
|
205
|
+ }
|
|
206
|
+
|
|
207
|
+ if (scan->value < datum) {
|
|
208
|
+ datpoint->point = scanold->point;
|
|
209
|
+ scanold->point = datpoint;
|
|
210
|
+ datum = STOPPER;
|
|
211
|
+ }
|
|
212
|
+
|
|
213
|
+ if (scan == &small) {
|
|
214
|
+ break;
|
|
215
|
+ }
|
|
216
|
+
|
|
217
|
+ scanold = scan;
|
|
218
|
+ scan = scan->point;
|
|
219
|
+ }
|
|
220
|
+ return median->value;
|
143
|
221
|
}
|
|
222
|
+};
|
|
223
|
+
|
|
224
|
+struct LowpassFilter {
|
|
225
|
+ uint32_t data_delay = 0;
|
144
|
226
|
uint16_t update(uint16_t value) {
|
145
|
|
- values[next_val++] = value;
|
146
|
|
- next_val = next_val % 3;
|
147
|
|
- return max(min(values[0], values[1]), min(max(values[0], values[1]), values[2])); //median
|
|
227
|
+ data_delay = data_delay - (data_delay >> ADC_LOWPASS_K_VALUE) + value;
|
|
228
|
+ return (uint16_t)(data_delay >> ADC_LOWPASS_K_VALUE);
|
148
|
229
|
}
|
149
|
230
|
};
|
150
|
231
|
|
151
|
|
-uint16_t lowpass_filter(uint16_t value) {
|
152
|
|
- const uint8_t k_data_shift = ADC_LOWPASS_K_VALUE;
|
153
|
|
- static uint32_t data_delay[NUM_ANALOG_INPUTS] = { 0 };
|
154
|
|
- uint32_t &active_filter = data_delay[active_adc];
|
155
|
|
- active_filter = active_filter - (active_filter >> k_data_shift) + value;
|
156
|
|
- return (uint16_t)(active_filter >> k_data_shift);
|
157
|
|
-}
|
158
|
|
-
|
159
|
232
|
uint16_t HAL_adc_get_result(void) {
|
160
|
|
- uint32_t data = LPC_ADC->ADGDR;
|
161
|
|
- CBI(LPC_ADC->ADCR, 24); // Stop conversion
|
162
|
|
- if (data & ADC_OVERRUN) return 0;
|
|
233
|
+ uint32_t adgdr = LPC_ADC->ADGDR;
|
|
234
|
+ CBI(LPC_ADC->ADCR, 24); // Stop conversion
|
|
235
|
+
|
|
236
|
+ if (adgdr & ADC_OVERRUN) return 0;
|
|
237
|
+ uint16_t data = (adgdr >> 4) & 0xFFF; // copy the 12bit data value
|
|
238
|
+ uint8_t adc_channel = (adgdr >> 24) & 0x7; // copy the 3bit used channel
|
|
239
|
+
|
163
|
240
|
#ifdef ADC_USE_MEDIAN_FILTER
|
164
|
241
|
static MedianFilter median_filter[NUM_ANALOG_INPUTS];
|
165
|
|
- data = median_filter[active_adc].update((uint16_t)data);
|
|
242
|
+ data = median_filter[adc_channel].update(data);
|
166
|
243
|
#endif
|
|
244
|
+
|
167
|
245
|
#ifdef ADC_USE_LOWPASS_FILTER
|
168
|
|
- data = lowpass_filter((uint16_t)data);
|
|
246
|
+ static LowpassFilter lowpass_filter[NUM_ANALOG_INPUTS];
|
|
247
|
+ data = lowpass_filter[adc_channel].update(data);
|
169
|
248
|
#endif
|
170
|
|
- return ((data >> 6) & 0x3ff); // 10bit
|
|
249
|
+
|
|
250
|
+ return ((data >> 2) & 0x3ff); // return 10bit value as Marlin expects
|
171
|
251
|
}
|
172
|
252
|
|
173
|
253
|
#define SBIT_CNTEN 0
|
|
@@ -187,8 +267,8 @@ void HAL_pwm_init(void) {
|
187
|
267
|
LPC_PWM1->TCR = _BV(SBIT_CNTEN) | _BV(SBIT_PWMEN);
|
188
|
268
|
LPC_PWM1->PR = 0x0; // No prescalar
|
189
|
269
|
LPC_PWM1->MCR = _BV(SBIT_PWMMR0R); // Reset on PWMMR0, reset TC if it matches MR0
|
190
|
|
- LPC_PWM1->MR0 = 255; /* set PWM cycle(Ton+Toff)=255) */
|
191
|
|
- LPC_PWM1->MR5 = 0; /* Set 50% Duty Cycle for the channels */
|
|
270
|
+ LPC_PWM1->MR0 = 255; // set PWM cycle(Ton+Toff)=255)
|
|
271
|
+ LPC_PWM1->MR5 = 0; // Set 50% Duty Cycle for the channels
|
192
|
272
|
LPC_PWM1->MR6 = 0;
|
193
|
273
|
|
194
|
274
|
// Trigger the latch Enable Bits to load the new Match Values MR0, MR5, MR6
|