lotus: Remove usage of chibios ADC API
Signed-off-by: Daniel Schaefer <dhs@frame.work>
This commit is contained in:
parent
27f17bad10
commit
ec581fd0a4
@ -11,7 +11,6 @@
|
||||
|
||||
enum factory_commands {
|
||||
f_emu_keypress = 0x01, // Next byte is keycode
|
||||
f_adc = 0x03, // ADC trigger
|
||||
f_serialnum = 0x04, // Read device serial number
|
||||
f_bootloader = 0xFE,
|
||||
};
|
||||
@ -49,9 +48,6 @@ void handle_factory_command(uint8_t *data) {
|
||||
tap_code(command_data[0]);
|
||||
#endif
|
||||
break;
|
||||
case f_adc:
|
||||
factory_trigger_adc();
|
||||
break;
|
||||
case f_serialnum:
|
||||
print("Reading Device serial number\n");
|
||||
|
||||
|
||||
@ -13,31 +13,8 @@
|
||||
#include "matrix.h"
|
||||
#include "lotus.h"
|
||||
|
||||
// Use raw ChibiOS ADC functions instead of those from QMK
|
||||
// Using the QMK functions doesn't work yet
|
||||
#define CHIBIOS_ADC FALSE
|
||||
|
||||
#define adc10ksample_t int
|
||||
|
||||
uint32_t prev_matrix_ts = 0;
|
||||
adc10ksample_t adc_voltage;
|
||||
#if CHIBIOS_ADC
|
||||
bool letsgo = false;
|
||||
adc10ksample_t temperature;
|
||||
|
||||
enum sample_state {
|
||||
s_never, // Never received a sample
|
||||
s_waiting, // Waiting for a new sample (at least one received)
|
||||
s_ready, // Received a sample, ready to be consumed
|
||||
};
|
||||
#define ADC_RESOLUTION 10
|
||||
#define ADC_GRP_NUM_CHANNELS 2
|
||||
#define ADC_GRP_BUF_DEPTH 2
|
||||
static adcsample_t prev_samples[CACHE_SIZE_ALIGN(adcsample_t, ADC_GRP_NUM_CHANNELS * ADC_GRP_BUF_DEPTH)];
|
||||
static adcsample_t samples[CACHE_SIZE_ALIGN(adcsample_t, ADC_GRP_NUM_CHANNELS * ADC_GRP_BUF_DEPTH)];
|
||||
static enum sample_state adc_state;
|
||||
#endif
|
||||
|
||||
// Mux GPIOs
|
||||
#define MUX_A GP1
|
||||
#define MUX_B GP2
|
||||
@ -69,138 +46,21 @@ static enum sample_state adc_state;
|
||||
#define KSO15 GP22
|
||||
|
||||
#define ADC_CH2_PIN GP28
|
||||
// Voltage threshold - TODO: Need to adjust
|
||||
|
||||
// Voltage threshold - anything below that counts as pressed
|
||||
const adc10ksample_t ADC_THRESHOLD = (adc10ksample_t) 3.0 * 10000;
|
||||
|
||||
adc10ksample_t to_voltage(adcsample_t sample) {
|
||||
#if CHIBIOS_ADC
|
||||
// 1241 = (1 << 12) * 10000 / (3.3 * 10000)
|
||||
int voltage = sample * 10000;
|
||||
return voltage / 1241;
|
||||
#else
|
||||
int voltage = sample * 33000;
|
||||
return voltage / 1023;
|
||||
#endif
|
||||
}
|
||||
|
||||
adc10ksample_t to_temp(adcsample_t sample) {
|
||||
int temp = sample * 10000;
|
||||
// Scaled up by 10000
|
||||
//temperature = 27.0 - (temp - 0.706)/0.001721;
|
||||
return 270000 - (((temp / 8) - 7060) /17);//.21;
|
||||
}
|
||||
void print_as_float(adc10ksample_t sample) {
|
||||
int digits = sample / 10000;
|
||||
int decimals = sample % 10000;
|
||||
uprintf("%d.%02d\n", digits, decimals);
|
||||
}
|
||||
|
||||
#if CHIBIOS_ADC
|
||||
/**
|
||||
* Average the mulitiple samples due to depth>1 together to a single value
|
||||
*/
|
||||
adcsample_t average_samples(adcsample_t s[], int channel) {
|
||||
adcsample_t sum = 0;
|
||||
assert(ADC_GRP_BUF_DEPTH == 2);
|
||||
|
||||
for (int i = 0; i < ADC_GRP_NUM_CHANNELS; i++) {
|
||||
sum += s[channel + (i * ADC_GRP_BUF_DEPTH)];
|
||||
}
|
||||
|
||||
return sum / ADC_GRP_NUM_CHANNELS;
|
||||
}
|
||||
|
||||
void print_samples(adcsample_t s[]) {
|
||||
// Samples go from 0 to 4095
|
||||
//uprintf("Raw ADC samples: %d, %d, %d, %d\n", samples[0], samples[1], samples[2], samples[3]);
|
||||
|
||||
print("Temp: ");
|
||||
print_as_float(temperature);
|
||||
|
||||
uprintf("ADC Voltage: ");
|
||||
print_as_float(adc_voltage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the ADC samples to meaningful values
|
||||
*
|
||||
* Should be called after receiving a set of samples from the ADC
|
||||
*/
|
||||
void handle_sample(void) {
|
||||
adcsample_t adv_avg = average_samples(samples, 0);
|
||||
adcsample_t temp_avg = average_samples(samples, 1);
|
||||
|
||||
// Uses global variables because it might be called from an interrupt handler
|
||||
// But we might not want to act upon them from there.
|
||||
// Convert to real temperature based on RP2040 datasheet
|
||||
temperature = to_temp(temp_avg);
|
||||
adc_voltage = to_voltage(adv_avg);
|
||||
|
||||
//print_samples(samples);
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back function which is called when ADC is finished.
|
||||
*/
|
||||
void adc_end_callback(ADCDriver *adcp) {
|
||||
(void)adcp;
|
||||
adc_state = s_ready;
|
||||
//print("adc_end_callback\n");
|
||||
|
||||
//handle_sample();
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back function which called when ADC gives some error.
|
||||
*/
|
||||
void adc_error_callback(ADCDriver *adcp, adcerror_t err) {
|
||||
(void)adcp;
|
||||
uprintf("error: %ld\n", err);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
const ADCConversionGroup adcConvGroup = {
|
||||
.circular = false,
|
||||
.num_channels = ADC_GRP_NUM_CHANNELS,
|
||||
.end_cb = &adc_end_callback,
|
||||
.error_cb = &adc_error_callback,
|
||||
// CH2 is the keyboard matrix, CH4 is the temp sensor
|
||||
.channel_mask = RP_ADC_CH2 | RP_ADC_CH4,
|
||||
};
|
||||
|
||||
/**
|
||||
* Trigger an ADC conversion. When done, the callback is called.
|
||||
*
|
||||
* Never blocks.
|
||||
* If adcConvGroup.circular is true, callbacks will keep coming.
|
||||
*/
|
||||
void trigger_adc(void) {
|
||||
adcStartConversion(&ADCD1, &adcConvGroup,
|
||||
samples, ADC_GRP_BUF_DEPTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a single, blocking ADC conversion
|
||||
*/
|
||||
void factory_trigger_adc(void) {
|
||||
if (!letsgo) {
|
||||
print("Factory triggered ADC\n");
|
||||
letsgo = true;
|
||||
}
|
||||
// adcConvert brings frequency from 6kHz down to 360Hz
|
||||
adcConvert(&ADCD1, &adcConvGroup,
|
||||
samples, ADC_GRP_BUF_DEPTH);
|
||||
//print("After adcConvert\n");
|
||||
memcpy(prev_samples, samples, sizeof(samples));
|
||||
handle_sample();
|
||||
//print("After handle_sample");
|
||||
}
|
||||
#else
|
||||
void factory_trigger_adc(void) {
|
||||
print("NOT IMPLEMENTED - Factory triggered ADC\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Tell RP2040 ADC controller to initialize a specific GPIO for ADC input
|
||||
*/
|
||||
@ -260,7 +120,6 @@ static void mux_select_row(int row) {
|
||||
writePin(MUX_C, bits[2]);
|
||||
}
|
||||
|
||||
#if 1
|
||||
/**
|
||||
* Based on the ADC value, update the matrix for this column
|
||||
* */
|
||||
@ -277,7 +136,6 @@ static bool interpret_adc_row(matrix_row_t cur_matrix[], adc10ksample_t voltage,
|
||||
key_state = true;
|
||||
}
|
||||
|
||||
//if (key_state) {
|
||||
if (key_state) {
|
||||
uprintf("Col %d - Row %d - State: %d, Voltage: ", col, row, key_state);
|
||||
print_as_float(voltage);
|
||||
@ -303,11 +161,8 @@ static bool interpret_adc_row(matrix_row_t cur_matrix[], adc10ksample_t voltage,
|
||||
}
|
||||
cur_matrix[row] = new_row;
|
||||
|
||||
// Debug keyboard
|
||||
//return false;
|
||||
return changed;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Drive the GPIO for a column low or high.
|
||||
@ -388,43 +243,12 @@ void drive_col(int col, bool high) {
|
||||
/**
|
||||
* Read a value from the ADC and print some debugging details
|
||||
*/
|
||||
static void read_adc(void) {
|
||||
#if !CHIBIOS_ADC
|
||||
// Can't use analogReadPin because it gets rid of the internal pullup on this pin
|
||||
//uint16_t val = analogReadPin(ADC_CH2_PIN);
|
||||
static adc10ksample_t read_adc(void) {
|
||||
// Can't use analogReadPin because it gets rid of the internal pullup on
|
||||
// this pin, that we configure in matrix_init_custom
|
||||
// uint16_t val = analogReadPin(ADC_CH2_PIN);
|
||||
uint16_t val = adc_read(pinToMux(ADC_CH2_PIN));
|
||||
adc_voltage = to_voltage(val);
|
||||
//uprintf("ADC raw %d, Voltage: ", val);
|
||||
//print_as_float(to_voltage(val));
|
||||
#else
|
||||
if (letsgo) {
|
||||
factory_trigger_adc();
|
||||
}
|
||||
|
||||
// Interrupt-driven
|
||||
// Even the "blocking" one suspends the thread, so we shouldn't need this
|
||||
//if (adc_state == s_ready) {
|
||||
// print("new sample\n");
|
||||
|
||||
// memcpy(prev_samples, samples, sizeof(samples));
|
||||
|
||||
// adc_state = s_waiting;
|
||||
|
||||
// // Works if both are commented out.
|
||||
// // Doesn't work if we don't sleep at all or sleep less than 300ms.
|
||||
// // Then we seemingly are stuck, no prints and doesn't respond to raw HID commands.
|
||||
// //
|
||||
// // Also works if we never trigger ADC at all
|
||||
// //hThdSleepMilliseconds(300);
|
||||
// // Trigger non-blocking ADC read that will be handled by and interrupt callback
|
||||
// trigger_adc();
|
||||
//}
|
||||
#endif // CHIBIOS_ADC
|
||||
|
||||
//uprintf("Temperature: ");
|
||||
//print_as_float(temperature);
|
||||
//uprintf("ADC Voltage: ");
|
||||
//print_as_float(adc_voltage);
|
||||
return to_voltage(val);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -447,15 +271,6 @@ void handle_idle(void) {
|
||||
bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||
bool changed = false;
|
||||
|
||||
//print("scan\n");
|
||||
|
||||
uint32_t current_ts = timer_read32();
|
||||
if (prev_matrix_ts) {
|
||||
//uint32_t delta = current_ts - prev_matrix_ts;
|
||||
//uprintf("%lu ms (%ld Hz)\n", delta, 1000 / delta);
|
||||
}
|
||||
prev_matrix_ts = current_ts;
|
||||
|
||||
handle_idle();
|
||||
|
||||
//wait_us(500 * 1000);
|
||||
@ -463,59 +278,6 @@ bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||
for (int col = 0; col < MATRIX_COLS; col++) {
|
||||
drive_col(col, true);
|
||||
}
|
||||
//drive_col(2, false);
|
||||
|
||||
// Striped red/black
|
||||
//
|
||||
// Shows low when not pressing. High when pressing. REVERSED!
|
||||
//
|
||||
// If no col is driven high. No cols work. (Row always low)
|
||||
// If all cols are driven high. Col 4 works. (high when pressed)
|
||||
// If just col 4 is driven high. Col 4 works. (high when pressed)
|
||||
//mux_select_row(3);
|
||||
|
||||
// Black
|
||||
// Shows low when not pressing. High when pressing. REVERSED!
|
||||
//
|
||||
// Correctly works only for the col that is driven high. REVERSED!
|
||||
// If all cols are driven high. All cols work. (high when pressed)
|
||||
// If no col is driven high. No cols work (high when pressed)
|
||||
//mux_select_row(2);
|
||||
|
||||
// Red
|
||||
//
|
||||
// High when not pressing. Low when pressing.
|
||||
// If no col is driven low. No cols work.
|
||||
// If all cols are driven low. All cols work. (low when pressed)
|
||||
// If just col 0 is driven low. Only col 0/GP8 works
|
||||
// If just col 1 is driven low. Only col 1/GP9 works
|
||||
// If just col 2 is driven low. Only col 2/GP10 works
|
||||
// If just col 3 is driven low. Only col 3/GP11 works
|
||||
// If just col 4 is driven low. Only col 4/GP12 works
|
||||
// If just col 5 is driven low. Only col 5/GP13 works
|
||||
// If just col 6 is driven low. Only col 6/GP14 works
|
||||
// If just col 7 is driven low. Only col 7/GP15 works
|
||||
//mux_select_row(1);
|
||||
|
||||
// Blue.
|
||||
// High when not pressing. Low when pressing.
|
||||
//
|
||||
// If no col is driven low. No cols work.
|
||||
// If all cols are driven low. All cols work. (low when pressed)
|
||||
// If just col 0 is driven low. Only col 0/GP8 works
|
||||
// If just col 1 is driven low. Only col 1/GP9 works
|
||||
// If just col 2 is driven low. Only col 2/GP10 works
|
||||
// If just col 3 is driven low. Only col 3/GP11 works
|
||||
// If just col 4 is driven low. Only col 4/GP12 works
|
||||
// If just col 5 is driven low. Only col 5/GP13 works
|
||||
// If just col 6 is driven low. Only col 6/GP14 works
|
||||
// If just col 7 is driven low. Only col 7/GP15 works
|
||||
//mux_select_row(0);
|
||||
//
|
||||
//wait_us(100);
|
||||
//read_adc();
|
||||
//uprintf("ADC Voltage: ");
|
||||
//print_as_float(adc_voltage);
|
||||
|
||||
// Go through every matrix column (KSO) and drive them low individually
|
||||
// Then go through every matrix row (KSI), select it with the mux and check their ADC value
|
||||
@ -531,18 +293,14 @@ bool matrix_scan_custom(matrix_row_t current_matrix[]) {
|
||||
// Wait for column select to settle and propagate to ADC
|
||||
//wait_us(500 * 1000);
|
||||
|
||||
read_adc();
|
||||
|
||||
// Interpret ADC value as rows
|
||||
changed |= interpret_adc_row(current_matrix, adc_voltage, col, row);
|
||||
changed |= interpret_adc_row(current_matrix, read_adc(), col, row);
|
||||
}
|
||||
|
||||
// Drive column high again
|
||||
drive_col(col, true);
|
||||
}
|
||||
|
||||
//uprintf("changed: %d\n", changed);
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
@ -600,32 +358,4 @@ void matrix_init_custom(void) {
|
||||
// Set unused pins to input to avoid interfering. They're hooked up to rows 5 and 6
|
||||
setPinInput(GP6);
|
||||
setPinInput(GP7);
|
||||
|
||||
#if CHIBIOS_ADC
|
||||
adc_state = s_never;
|
||||
const ADCConfig adcConfig = {
|
||||
// Default clock divider
|
||||
.div_int = 0,
|
||||
.div_frac = 0,
|
||||
// Don't shift FIFO results
|
||||
.shift = false,
|
||||
};
|
||||
adcStart(&ADCD1, &adcConfig);
|
||||
|
||||
// For testing enable temp sensor
|
||||
adcRPEnableTS(&ADCD1);
|
||||
|
||||
// Start ADC conversion immediately. Don't wait for factory command to enable
|
||||
// For debugging it's sometimes useful to start later because the first
|
||||
// prints won't show on the console. So if it hangs here, it's hard to tell
|
||||
// what's going wrong.
|
||||
letsgo = true;
|
||||
|
||||
// Start automatic conversion
|
||||
//chThdSleepMilliseconds(100);
|
||||
//trigger_adc();
|
||||
|
||||
// TODO: Not sure we ever need to stop. Perhaps to save power.
|
||||
// adcStopConversion(&ADCD1);
|
||||
#endif
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user