made the gyro board analog stuff actually work
diff --git a/frc971/input/usb_receiver.cc b/frc971/input/usb_receiver.cc
index c5117d7..06eb7df 100644
--- a/frc971/input/usb_receiver.cc
+++ b/frc971/input/usb_receiver.cc
@@ -183,7 +183,6 @@
void USBReceiver::TransferCallback(libusb::Transfer *transfer) {
transfer_received_time_ = ::aos::time::Time::Now();
if (transfer->status() == LIBUSB_TRANSFER_COMPLETED) {
- LOG(DEBUG, "transfer %p completed\n", transfer);
completed_transfer_ = transfer;
} else if (transfer->status() == LIBUSB_TRANSFER_TIMED_OUT) {
LOG(WARNING, "transfer %p timed out\n", transfer);
diff --git a/gyro_board/schematic/.gitignore b/gyro_board/schematic/.gitignore
new file mode 100644
index 0000000..d6b9d75
--- /dev/null
+++ b/gyro_board/schematic/.gitignore
@@ -0,0 +1,2 @@
+*.b#*
+*.s#*
diff --git a/gyro_board/src/usb/analog.c b/gyro_board/src/usb/analog.c
index 8dcaf26..7968094 100644
--- a/gyro_board/src/usb/analog.c
+++ b/gyro_board/src/usb/analog.c
@@ -1,52 +1,81 @@
#include "analog.h"
#include "LPC17xx.h"
+#include "FreeRTOS.h"
-#define USE_BURST 0
+static int discarded_samples[4];
+
+static uint16_t raw_analog(int channel) {
+ uint32_t value;
+ switch (channel) {
+ case 0:
+ value = ADC->ADDR0;
+ break;
+ case 1:
+ value = ADC->ADDR1;
+ break;
+ case 2:
+ value = ADC->ADDR2;
+ break;
+ case 3:
+ value = ADC->ADDR3;
+ break;
+ }
+
+ return (value >> 4) & 0xFFF;
+}
+
+void TIMER1_IRQHandler(void) {
+ TIM1->IR = 1 << 0; // clear channel 0 match
+
+ static const int kBadSampleThreshold = 175;
+ static const int kMaxBadSamples = 4;
+
+ static const uint32_t kBitShift = 16;
+ static const uint32_t kA =
+ (1.0 - 0.8408964152537146 /*0.5^0.25*/) * (1 << kBitShift) + 0.5;
+ for (int i = 0; i < 4; ++i) {
+ uint16_t current = raw_analog(i);
+ uint16_t average = averaged_values[i];
+ if ((current - average) < -kBadSampleThreshold ||
+ (current - average) > kBadSampleThreshold) {
+ ++discarded_samples[i];
+ if (discarded_samples[i] >= kMaxBadSamples) {
+ discarded_samples[i] = 0;
+ averaged_values[i] = current;
+ }
+ } else {
+ discarded_samples[i] = 0;
+ averaged_values[i] =
+ ((uint32_t)current * kA +
+ (uint32_t)average * ((1 << kBitShift) - kA)) >> kBitShift;
+ }
+ }
+}
void analog_init(void) {
SC->PCONP |= PCONP_PCAD;
- // Enable AD0.0, AD0.1, AD0.2, and AD0.3.
+ // Enable AD0.0, AD0.1, AD0.2, and AD0.3 (0.23 - 0.26).
PINCON->PINSEL1 &= ~(3 << 14 | 3 << 16 | 3 << 18 | 3 << 20);
PINCON->PINSEL1 |= 1 << 14 | 1 << 16 | 1 << 18 | 1 << 20;
+ PINCON->PINMODE1 &= ~(3 << 14 | 3 << 16 | 3 << 18 | 3 << 20);
+ PINCON->PINMODE1 |= 2 << 14 | 2 << 16 | 2 << 18 | 2 << 20;
-#if USE_BURST
ADC->ADCR = (1 << 0 | 1 << 1 | 1 << 2 | 1 << 3) /* enable all 4 */ |
- 7 << 8 /* 100MHz / 8 = 12.5MHz */ |
+ 79 << 8 /* takes 208us to scan through all 4 */ |
1 << 16 /* enable burst mode */ |
1 << 21 /* turn on ADC */;
-#else
- ADC->ADCR = 7 << 8 /* 100MHz / 8 = 12.5MHz */ |
- 1 << 21 /* turn on ADC */;
-#endif
-}
-uint16_t analog(int channel) {
-#if !USE_BURST
- // Set the channel number to the one we want.
- ADC->ADCR = (ADC->ADCR & ~0xFF) | (1 << channel);
- ADC->ADCR |= 1 << 24; // start conversion
-#endif
- uint32_t value;
- do {
- switch (channel) {
- case 0:
- value = ADC->ADDR0;
- break;
- case 1:
- value = ADC->ADDR1;
- break;
- case 2:
- value = ADC->ADDR2;
- break;
- case 3:
- value = ADC->ADDR3;
- break;
- default:
- return 0xFFFF;
- }
- } while (!(value & 1 << 31));
-
- return (value >> 4) & 0x3FF;
+ // Set up the timer for the low-pass filter.
+ SC->PCONP |= 1 << 2;
+ TIM1->PR = (configCPU_CLOCK_HZ / 2000) - 1;
+ TIM1->TC = 0; // don't match the first time around
+ TIM1->MR0 = 1; // match every time it wraps
+ TIM1->MCR = 1 << 0 | 1 << 1; // interrupt and reset on match channel 0
+ // Priority 4 is higher than any FreeRTOS-managed stuff (ie USB), but lower
+ // than encoders etc.
+ NVIC_SetPriority(TIMER1_IRQn, 4);
+ NVIC_EnableIRQ(TIMER1_IRQn);
+ TIM1->TCR = 1; // enable it
}
diff --git a/gyro_board/src/usb/analog.h b/gyro_board/src/usb/analog.h
index 5a06290..acbf679 100644
--- a/gyro_board/src/usb/analog.h
+++ b/gyro_board/src/usb/analog.h
@@ -3,13 +3,22 @@
#include <stdint.h>
+// Internal variable for holding the averaged value. USE analog TO GET TO THIS
+// IN CASE IT CHANGES!
+uint16_t averaged_values[4];
+
// Starts the hardware constantly doing conversions on all 4 of our analog
// inputs.
void analog_init(void);
// Retrieves the most recent reading on channel (0-3).
// Returns 0xFFFF for invalid channel.
-// 0 means 0V and 0x3FF means 3.3V.
-uint16_t analog(int channel);
+// 0 means 0V and 0xFFF means 3.3V.
+// These values are run through a low-pass filter with unreasonable readings
+// discarded first.
+uint16_t analog(int channel) {
+ if (channel < 0 || channel > 3) return 0xFFFF;
+ return averaged_values[channel];
+}
#endif // __ANALOG_H__
diff --git a/gyro_board/src/usb/encoder.c b/gyro_board/src/usb/encoder.c
index c04a8b8..c9155d4 100644
--- a/gyro_board/src/usb/encoder.c
+++ b/gyro_board/src/usb/encoder.c
@@ -553,8 +553,8 @@
// Do all of the analogs last because they have the potential to be slow and
// jittery.
- packet->main.battery_voltage = analog(3);
- packet->main.left_drive_hall = analog(1);
+ packet->main.battery_voltage = analog(1);
+ packet->main.left_drive_hall = analog(3);
packet->main.right_drive_hall = analog(2);
}
}