Fixes post rebase
This commit is contained in:
parent
33c0453515
commit
a5572e5e44
|
@ -1,13 +1 @@
|
|||
add_library(encoder-pio INTERFACE)
|
||||
|
||||
target_sources(encoder-pio INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/encoder.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/capture.cpp
|
||||
)
|
||||
|
||||
pico_generate_pio_header(encoder-pio ${CMAKE_CURRENT_LIST_DIR}/encoder.pio)
|
||||
|
||||
target_include_directories(encoder-pio INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(encoder-pio INTERFACE pico_stdlib hardware_pio)
|
||||
include(encoder-pio.cmake)
|
|
@ -10,7 +10,7 @@ namespace pimoroni {
|
|||
//--------------------------------------------------
|
||||
private:
|
||||
const int32_t captured_count = 0;
|
||||
const int32_t count_change = 0;
|
||||
const int32_t count_change = 0;
|
||||
const float average_frequency = 0.0f;
|
||||
const float counts_per_revolution = 1;
|
||||
|
||||
|
@ -34,7 +34,7 @@ namespace pimoroni {
|
|||
|
||||
int32_t get_count_change() const;
|
||||
|
||||
float get_frequency() const;
|
||||
float get_frequency() const;
|
||||
float get_revolutions_per_second() const;
|
||||
float get_revolutions_per_minute() const;
|
||||
float get_degrees_per_second() const;
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
add_library(encoder-pio INTERFACE)
|
||||
set(DRIVER_NAME encoder-pio)
|
||||
add_library(${DRIVER_NAME} INTERFACE)
|
||||
|
||||
target_sources(encoder-pio INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/msa301.cpp
|
||||
target_sources(${DRIVER_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/encoder.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/capture.cpp
|
||||
)
|
||||
|
||||
pico_generate_pio_header(encoder-pio ${CMAKE_CURRENT_LIST_DIR}/encoder.pio)
|
||||
pico_generate_pio_header(${DRIVER_NAME} ${CMAKE_CURRENT_LIST_DIR}/encoder.pio)
|
||||
|
||||
target_include_directories(encoder-pio INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(encoder-pio INTERFACE pico_stdlib hardware_i2c)
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE
|
||||
pico_stdlib
|
||||
hardware_pio
|
||||
)
|
|
@ -17,7 +17,7 @@ namespace pimoroni {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Encoder::pio0_interrupt_callback() {
|
||||
//Go through each of encoders on this PIO to see which triggered this interrupt
|
||||
// Go through each of encoders on this PIO to see which triggered this interrupt
|
||||
for(uint8_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) {
|
||||
if(pio_encoders[0][sm] != nullptr) {
|
||||
pio_encoders[0][sm]->check_for_transition();
|
||||
|
@ -27,7 +27,7 @@ namespace pimoroni {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void Encoder::pio1_interrupt_callback() {
|
||||
//Go through each of encoders on this PIO to see which triggered this interrupt
|
||||
// Go through each of encoders on this PIO to see which triggered this interrupt
|
||||
for(uint8_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) {
|
||||
if(pio_encoders[1][sm] != nullptr) {
|
||||
pio_encoders[1][sm]->check_for_transition();
|
||||
|
@ -41,7 +41,7 @@ namespace pimoroni {
|
|||
// CONSTRUCTORS / DESTRUCTOR
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Encoder::Encoder(PIO pio, uint8_t pinA, uint8_t pinB, uint8_t pinC,
|
||||
float counts_per_revolution, bool count_microsteps,
|
||||
float counts_per_revolution, bool count_microsteps,
|
||||
uint16_t freq_divider) :
|
||||
enc_pio(pio), pinA(pinA), pinB(pinB), pinC(pinC),
|
||||
counts_per_revolution(counts_per_revolution), count_microsteps(count_microsteps),
|
||||
|
@ -50,13 +50,13 @@ namespace pimoroni {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Encoder::~Encoder() {
|
||||
//Clean up our use of the SM associated with this encoder
|
||||
// Clean up our use of the SM associated with this encoder
|
||||
encoder_program_release(enc_pio, enc_sm);
|
||||
uint index = pio_get_index(enc_pio);
|
||||
pio_encoders[index][enc_sm] = nullptr;
|
||||
pio_claimed_sms[index] &= ~(1u << enc_sm);
|
||||
|
||||
//If there are no more SMs using the encoder program, then we can remove it from the PIO
|
||||
// If there are no more SMs using the encoder program, then we can remove it from the PIO
|
||||
if(pio_claimed_sms[index] == 0) {
|
||||
pio_remove_program(enc_pio, &encoder_program, enc_offset);
|
||||
}
|
||||
|
@ -70,10 +70,10 @@ namespace pimoroni {
|
|||
bool Encoder::init() {
|
||||
bool initialised = false;
|
||||
|
||||
//Are the pins we want to use actually valid?
|
||||
// Are the pins we want to use actually valid?
|
||||
if((pinA < NUM_BANK0_GPIOS) && (pinB < NUM_BANK0_GPIOS)) {
|
||||
|
||||
//If a Pin C was defined, and valid, set it as a GND to pull the other two pins down
|
||||
// If a Pin C was defined, and valid, set it as a GND to pull the other two pins down
|
||||
if((pinC != PIN_UNUSED) && (pinC < NUM_BANK0_GPIOS)) {
|
||||
gpio_init(pinC);
|
||||
gpio_set_dir(pinC, GPIO_OUT);
|
||||
|
@ -83,9 +83,9 @@ namespace pimoroni {
|
|||
enc_sm = pio_claim_unused_sm(enc_pio, true);
|
||||
uint pio_idx = pio_get_index(enc_pio);
|
||||
|
||||
//Is this the first time using an encoder on this PIO?
|
||||
// Is this the first time using an encoder on this PIO?
|
||||
if(pio_claimed_sms[pio_idx] == 0) {
|
||||
//Add the program to the PIO memory and enable the appropriate interrupt
|
||||
// Add the program to the PIO memory and enable the appropriate interrupt
|
||||
enc_offset = pio_add_program(enc_pio, &encoder_program);
|
||||
encoder_program_init(enc_pio, enc_sm, enc_offset, pinA, pinB, freq_divider);
|
||||
hw_set_bits(&enc_pio->inte0, PIO_IRQ0_INTE_SM0_RXNEMPTY_BITS << enc_sm);
|
||||
|
@ -99,11 +99,11 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
//Keep a record of this encoder for the interrupt callback
|
||||
// Keep a record of this encoder for the interrupt callback
|
||||
pio_encoders[pio_idx][enc_sm] = this;
|
||||
pio_claimed_sms[pio_idx] |= 1u << enc_sm;
|
||||
|
||||
//Read the current state of the encoder pins and start the PIO program on the SM
|
||||
// Read the current state of the encoder pins and start the PIO program on the SM
|
||||
stateA = gpio_get(pinA);
|
||||
stateB = gpio_get(pinB);
|
||||
encoder_program_start(enc_pio, enc_sm, stateA, stateB);
|
||||
|
@ -175,18 +175,18 @@ namespace pimoroni {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
Capture Encoder::perform_capture() {
|
||||
//Capture the current values
|
||||
int32_t captured_count = count;
|
||||
int32_t captured_cumulative_time = cumulative_time;
|
||||
cumulative_time = 0;
|
||||
// Capture the current values
|
||||
int32_t captured_count = count;
|
||||
int32_t captured_cumulative_time = cumulative_time;
|
||||
cumulative_time = 0;
|
||||
|
||||
//Determine the change in counts since the last capture was performed
|
||||
int32_t count_change = captured_count - last_captured_count;
|
||||
last_captured_count = captured_count;
|
||||
// Determine the change in counts since the last capture was performed
|
||||
int32_t count_change = captured_count - last_captured_count;
|
||||
last_captured_count = captured_count;
|
||||
|
||||
//Calculate the average frequency of state transitions
|
||||
// Calculate the average frequency of state transitions
|
||||
float average_frequency = 0.0f;
|
||||
if(count_change != 0 && captured_cumulative_time != INT_MAX) {
|
||||
if(count_change != 0 && captured_cumulative_time != INT_MAX) {
|
||||
average_frequency = (clocks_per_time * (float)count_change) / (float)captured_cumulative_time;
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ namespace pimoroni {
|
|||
// For rotary encoders, only every fourth transition is cared about, causing an inaccurate time value
|
||||
// To address this we accumulate the times received and zero it when a transition is counted
|
||||
if(!count_microsteps) {
|
||||
if(time_received + microstep_time < time_received) //Check to avoid integer overflow
|
||||
if(time_received + microstep_time < time_received) // Check to avoid integer overflow
|
||||
time_received = INT32_MAX;
|
||||
else
|
||||
time_received += microstep_time;
|
||||
|
@ -256,7 +256,7 @@ namespace pimoroni {
|
|||
// B ____|‾‾‾‾
|
||||
case MICROSTEP_3:
|
||||
if(count_microsteps)
|
||||
microstep_down(time_received);
|
||||
microstep_down(time_received);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -270,7 +270,7 @@ namespace pimoroni {
|
|||
if(count_microsteps || last_travel_dir == CLOCKWISE)
|
||||
microstep_up(time_received);
|
||||
|
||||
last_travel_dir = NO_DIR; //Finished turning clockwise
|
||||
last_travel_dir = NO_DIR; // Finished turning clockwise
|
||||
break;
|
||||
|
||||
// A ‾‾‾‾|____
|
||||
|
@ -291,7 +291,7 @@ namespace pimoroni {
|
|||
if(count_microsteps)
|
||||
microstep_up(time_received);
|
||||
|
||||
last_travel_dir = CLOCKWISE; //Started turning clockwise
|
||||
last_travel_dir = CLOCKWISE; // Started turning clockwise
|
||||
break;
|
||||
|
||||
// A ‾‾‾‾‾‾‾‾‾
|
||||
|
@ -300,7 +300,7 @@ namespace pimoroni {
|
|||
if(count_microsteps)
|
||||
microstep_down(time_received);
|
||||
|
||||
last_travel_dir = COUNTERCLOCK; //Started turning counter-clockwise
|
||||
last_travel_dir = COUNTERCLOCK; // Started turning counter-clockwise
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -320,8 +320,8 @@ namespace pimoroni {
|
|||
case MICROSTEP_2:
|
||||
if(count_microsteps || last_travel_dir == COUNTERCLOCK)
|
||||
microstep_down(time_received);
|
||||
|
||||
last_travel_dir = NO_DIR; //Finished turning counter-clockwise
|
||||
|
||||
last_travel_dir = NO_DIR; // Finished turning counter-clockwise
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace pimoroni {
|
|||
public:
|
||||
static constexpr float DEFAULT_COUNTS_PER_REV = 24;
|
||||
static const uint16_t DEFAULT_COUNT_MICROSTEPS = false;
|
||||
static const uint16_t DEFAULT_FREQ_DIVIDER = 1;
|
||||
static const uint16_t DEFAULT_FREQ_DIVIDER = 1;
|
||||
static const uint8_t PIN_UNUSED = UINT8_MAX;
|
||||
|
||||
private:
|
||||
|
@ -58,7 +58,7 @@ namespace pimoroni {
|
|||
const float clocks_per_time = 0;
|
||||
|
||||
//--------------------------------------------------
|
||||
|
||||
|
||||
uint enc_sm = 0;
|
||||
uint enc_offset = 0;
|
||||
|
||||
|
@ -108,7 +108,7 @@ namespace pimoroni {
|
|||
float get_angle_degrees() const;
|
||||
float get_angle_radians() const;
|
||||
|
||||
float get_frequency() const;
|
||||
float get_frequency() const;
|
||||
float get_revolutions_per_second() const;
|
||||
float get_revolutions_per_minute() const;
|
||||
float get_degrees_per_second() const;
|
||||
|
|
|
@ -16,24 +16,24 @@ static const uint8_t ENCODER_PIN_B = 0;
|
|||
static const uint8_t ENCODER_PIN_C = Encoder::PIN_UNUSED;
|
||||
static const uint8_t ENCODER_SWITCH_PIN = 4;
|
||||
|
||||
static constexpr float COUNTS_PER_REVOLUTION = 24; //24 is for rotary encoders. For motor magnetic encoders uses
|
||||
//12 times the gear ratio (e.g. 12 * 20 with a 20:1 ratio motor
|
||||
static const bool COUNT_MICROSTEPS = false; //Set to true for motor magnetic encoders
|
||||
static constexpr float COUNTS_PER_REVOLUTION = 24; // 24 is for rotary encoders. For motor magnetic encoders uses
|
||||
// 12 times the gear ratio (e.g. 12 * 20 with a 20:1 ratio motor
|
||||
static const bool COUNT_MICROSTEPS = false; // Set to true for motor magnetic encoders
|
||||
|
||||
static const uint16_t FREQ_DIVIDER = 1; //Increase this to deal with switch bounce. 250 Gives a 1ms debounce
|
||||
static const uint16_t FREQ_DIVIDER = 1; // Increase this to deal with switch bounce. 250 Gives a 1ms debounce
|
||||
|
||||
static const int32_t TIME_BETWEEN_SAMPLES_US = 100; //Time between each sample, in microseconds
|
||||
static const int32_t WINDOW_DURATION_US = 1000000; //The full time window that will be stored
|
||||
static const int32_t TIME_BETWEEN_SAMPLES_US = 100; // Time between each sample, in microseconds
|
||||
static const int32_t WINDOW_DURATION_US = 1000000; // The full time window that will be stored
|
||||
|
||||
static const int32_t READINGS_SIZE = WINDOW_DURATION_US / TIME_BETWEEN_SAMPLES_US;
|
||||
static const int32_t SCRATCH_SIZE = READINGS_SIZE / 10; //A smaller value, for temporarily storing readings during screen drawing
|
||||
static const int32_t SCRATCH_SIZE = READINGS_SIZE / 10; // A smaller value, for temporarily storing readings during screen drawing
|
||||
|
||||
static const bool QUADRATURE_OUT_ENABLED = true;
|
||||
static constexpr float QUADRATURE_OUT_FREQ = 800; //The frequency the quadrature output will run at (note that counting microsteps will show 4x this value)
|
||||
static const float QUADRATURE_OUT_1ST_PIN = 6; //Which first pin to output the quadrature signal to (e.g. pins 6 and 7)
|
||||
static constexpr float QUADRATURE_OUT_FREQ = 800; // The frequency the quadrature output will run at (note that counting microsteps will show 4x this value)
|
||||
static const float QUADRATURE_OUT_1ST_PIN = 6; // Which first pin to output the quadrature signal to (e.g. pins 6 and 7)
|
||||
|
||||
static const uint64_t MAIN_LOOP_TIME_US = 50000; //How long there should be in microseconds between each screen refresh
|
||||
static const uint16_t EDGE_ALIGN_ABOVE_ZOOM = 4; //The zoom level beyond which edge alignment will be enabled to ma
|
||||
static const uint64_t MAIN_LOOP_TIME_US = 50000; // How long there should be in microseconds between each screen refresh
|
||||
static const uint16_t EDGE_ALIGN_ABOVE_ZOOM = 4; // The zoom level beyond which edge alignment will be enabled to ma
|
||||
|
||||
|
||||
|
||||
|
@ -71,136 +71,131 @@ uint16_t current_zoom_level = 1;
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FUNCTIONS
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
uint32_t draw_plot(Point p1, Point p2, volatile bool (&readings)[READINGS_SIZE], uint32_t readingPos, bool edge_align)
|
||||
{
|
||||
uint32_t reading_window = READINGS_SIZE / current_zoom_level;
|
||||
uint32_t start_index_no_modulus = (readingPos + (READINGS_SIZE - reading_window));
|
||||
uint32_t start_index = start_index_no_modulus % READINGS_SIZE;
|
||||
int32_t screen_window = std::min(p2.x, (int32_t)PicoExplorer::WIDTH) - p1.x;
|
||||
uint32_t draw_plot(Point p1, Point p2, volatile bool (&readings)[READINGS_SIZE], uint32_t readingPos, bool edge_align) {
|
||||
uint32_t reading_window = READINGS_SIZE / current_zoom_level;
|
||||
uint32_t start_index_no_modulus = (readingPos + (READINGS_SIZE - reading_window));
|
||||
uint32_t start_index = start_index_no_modulus % READINGS_SIZE;
|
||||
int32_t screen_window = std::min(p2.x, (int32_t)PicoExplorer::WIDTH) - p1.x;
|
||||
|
||||
bool last_reading = readings[start_index % READINGS_SIZE];
|
||||
bool last_reading = readings[start_index % READINGS_SIZE];
|
||||
|
||||
uint32_t alignment_offset = 0;
|
||||
if(edge_align) {
|
||||
//Perform edge alignment by first seeing if there is a window of readings available (will be at anything other than x1 zoom)
|
||||
uint32_t align_window = (start_index_no_modulus - readingPos);
|
||||
uint32_t alignment_offset = 0;
|
||||
if(edge_align) {
|
||||
// Perform edge alignment by first seeing if there is a window of readings available (will be at anything other than x1 zoom)
|
||||
uint32_t align_window = (start_index_no_modulus - readingPos);
|
||||
|
||||
//Then go backwards through that window
|
||||
for(uint32_t i = 1; i < align_window; i++) {
|
||||
uint32_t align_index = (start_index + (READINGS_SIZE - i)) % READINGS_SIZE;
|
||||
bool align_reading = readings[align_index];
|
||||
// Then go backwards through that window
|
||||
for(uint32_t i = 1; i < align_window; i++) {
|
||||
uint32_t align_index = (start_index + (READINGS_SIZE - i)) % READINGS_SIZE;
|
||||
bool align_reading = readings[align_index];
|
||||
|
||||
//Has a transition from high to low been detected?
|
||||
if(!align_reading && align_reading != last_reading) {
|
||||
//Set the new start index from which to draw from and break out of the search
|
||||
start_index = align_index;
|
||||
alignment_offset = i;
|
||||
break;
|
||||
}
|
||||
last_reading = align_reading;
|
||||
}
|
||||
|
||||
last_reading = readings[start_index % READINGS_SIZE];
|
||||
// Has a transition from high to low been detected?
|
||||
if(!align_reading && align_reading != last_reading) {
|
||||
// Set the new start index from which to draw from and break out of the search
|
||||
start_index = align_index;
|
||||
alignment_offset = i;
|
||||
break;
|
||||
}
|
||||
last_reading = align_reading;
|
||||
}
|
||||
|
||||
//Go through each X pixel within the screen window
|
||||
uint32_t reading_window_start = 0;
|
||||
for(int32_t x = 0; x < screen_window; x++)
|
||||
{
|
||||
uint32_t reading_window_end = ((x + 1) * reading_window) / screen_window;
|
||||
last_reading = readings[start_index % READINGS_SIZE];
|
||||
}
|
||||
|
||||
//Set the draw state to be whatever the last reading was
|
||||
DrawState draw_state = last_reading ? DRAW_HIGH : DRAW_LOW;
|
||||
// Go through each X pixel within the screen window
|
||||
uint32_t reading_window_start = 0;
|
||||
for(int32_t x = 0; x < screen_window; x++) {
|
||||
uint32_t reading_window_end = ((x + 1) * reading_window) / screen_window;
|
||||
|
||||
//Go through the readings in this window to see if a transition from low to high or high to low occurs
|
||||
if(reading_window_end > reading_window_start) {
|
||||
for(uint32_t i = reading_window_start; i < reading_window_end; i++) {
|
||||
bool reading = readings[(i + start_index) % READINGS_SIZE];
|
||||
if(reading != last_reading) {
|
||||
draw_state = DRAW_TRANSITION;
|
||||
break; //A transition occurred, so no need to continue checking readings
|
||||
}
|
||||
last_reading = reading;
|
||||
}
|
||||
last_reading = readings[((reading_window_end - 1) + start_index) % READINGS_SIZE];
|
||||
}
|
||||
reading_window_start = reading_window_end;
|
||||
|
||||
//Draw a pixel in a high or low position, or a line between the two if a transition
|
||||
switch(draw_state)
|
||||
{
|
||||
case DRAW_TRANSITION:
|
||||
for(uint8_t y = p1.y; y < p2.y; y++)
|
||||
pico_explorer.pixel(Point(x + p1.x, y));
|
||||
break;
|
||||
case DRAW_HIGH:
|
||||
pico_explorer.pixel(Point(x + p1.x, p1.y));
|
||||
break;
|
||||
case DRAW_LOW:
|
||||
pico_explorer.pixel(Point(x + p1.x, p2.y - 1));
|
||||
break;
|
||||
// Set the draw state to be whatever the last reading was
|
||||
DrawState draw_state = last_reading ? DRAW_HIGH : DRAW_LOW;
|
||||
|
||||
// Go through the readings in this window to see if a transition from low to high or high to low occurs
|
||||
if(reading_window_end > reading_window_start) {
|
||||
for(uint32_t i = reading_window_start; i < reading_window_end; i++) {
|
||||
bool reading = readings[(i + start_index) % READINGS_SIZE];
|
||||
if(reading != last_reading) {
|
||||
draw_state = DRAW_TRANSITION;
|
||||
break; // A transition occurred, so no need to continue checking readings
|
||||
}
|
||||
last_reading = reading;
|
||||
}
|
||||
last_reading = readings[((reading_window_end - 1) + start_index) % READINGS_SIZE];
|
||||
}
|
||||
reading_window_start = reading_window_end;
|
||||
|
||||
//Return the alignment offset so subsequent encoder channel plots can share the alignment
|
||||
return alignment_offset;
|
||||
// Draw a pixel in a high or low position, or a line between the two if a transition
|
||||
switch(draw_state) {
|
||||
case DRAW_TRANSITION:
|
||||
for(uint8_t y = p1.y; y < p2.y; y++)
|
||||
pico_explorer.pixel(Point(x + p1.x, y));
|
||||
break;
|
||||
case DRAW_HIGH:
|
||||
pico_explorer.pixel(Point(x + p1.x, p1.y));
|
||||
break;
|
||||
case DRAW_LOW:
|
||||
pico_explorer.pixel(Point(x + p1.x, p2.y - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the alignment offset so subsequent encoder channel plots can share the alignment
|
||||
return alignment_offset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
bool repeating_timer_callback(struct repeating_timer *t) {
|
||||
if(drawing_to_screen && next_scratch_index < SCRATCH_SIZE) {
|
||||
encA_scratch[next_scratch_index] = encoder.get_state_a();
|
||||
encB_scratch[next_scratch_index] = encoder.get_state_b();
|
||||
next_scratch_index++;
|
||||
}
|
||||
else {
|
||||
encA_readings[next_reading_index] = encoder.get_state_a();
|
||||
encB_readings[next_reading_index] = encoder.get_state_b();
|
||||
if(drawing_to_screen && next_scratch_index < SCRATCH_SIZE) {
|
||||
encA_scratch[next_scratch_index] = encoder.get_state_a();
|
||||
encB_scratch[next_scratch_index] = encoder.get_state_b();
|
||||
next_scratch_index++;
|
||||
}
|
||||
else {
|
||||
encA_readings[next_reading_index] = encoder.get_state_a();
|
||||
encB_readings[next_reading_index] = encoder.get_state_b();
|
||||
|
||||
next_reading_index++;
|
||||
if(next_reading_index >= READINGS_SIZE)
|
||||
next_reading_index = 0;
|
||||
}
|
||||
next_reading_index++;
|
||||
if(next_reading_index >= READINGS_SIZE)
|
||||
next_reading_index = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void setup() {
|
||||
stdio_init_all();
|
||||
stdio_init_all();
|
||||
|
||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||
gpio_init(PICO_DEFAULT_LED_PIN);
|
||||
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
|
||||
|
||||
if(ENCODER_SWITCH_PIN != Encoder::PIN_UNUSED) {
|
||||
gpio_init(ENCODER_SWITCH_PIN);
|
||||
gpio_set_dir(ENCODER_SWITCH_PIN, GPIO_IN);
|
||||
gpio_pull_down(ENCODER_SWITCH_PIN);
|
||||
}
|
||||
if(ENCODER_SWITCH_PIN != Encoder::PIN_UNUSED) {
|
||||
gpio_init(ENCODER_SWITCH_PIN);
|
||||
gpio_set_dir(ENCODER_SWITCH_PIN, GPIO_IN);
|
||||
gpio_pull_down(ENCODER_SWITCH_PIN);
|
||||
}
|
||||
|
||||
pico_explorer.init();
|
||||
pico_explorer.set_pen(0);
|
||||
pico_explorer.clear();
|
||||
pico_explorer.update();
|
||||
pico_explorer.init();
|
||||
pico_explorer.set_pen(0);
|
||||
pico_explorer.clear();
|
||||
pico_explorer.update();
|
||||
|
||||
encoder.init();
|
||||
encoder.init();
|
||||
|
||||
bool encA = encoder.get_state_a();
|
||||
bool encB = encoder.get_state_b();
|
||||
for(uint i = 0; i < READINGS_SIZE; i++) {
|
||||
encA_readings[i] = encA;
|
||||
encB_readings[i] = encB;
|
||||
}
|
||||
bool encA = encoder.get_state_a();
|
||||
bool encB = encoder.get_state_b();
|
||||
for(uint i = 0; i < READINGS_SIZE; i++) {
|
||||
encA_readings[i] = encA;
|
||||
encB_readings[i] = encB;
|
||||
}
|
||||
|
||||
if(QUADRATURE_OUT_ENABLED) {
|
||||
//Set up the quadrature encoder output
|
||||
PIO pio = pio1;
|
||||
uint offset = pio_add_program(pio, &quadrature_out_program);
|
||||
uint sm = pio_claim_unused_sm(pio, true);
|
||||
quadrature_out_program_init(pio, sm, offset, QUADRATURE_OUT_1ST_PIN, QUADRATURE_OUT_FREQ);
|
||||
}
|
||||
|
||||
pico_explorer.set_backlight(255);
|
||||
if(QUADRATURE_OUT_ENABLED) {
|
||||
// Set up the quadrature encoder output
|
||||
PIO pio = pio1;
|
||||
uint offset = pio_add_program(pio, &quadrature_out_program);
|
||||
uint sm = pio_claim_unused_sm(pio, true);
|
||||
quadrature_out_program_init(pio, sm, offset, QUADRATURE_OUT_1ST_PIN, QUADRATURE_OUT_FREQ);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -210,136 +205,139 @@ void setup() {
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
int main() {
|
||||
|
||||
//Perform the main setup for the demo
|
||||
setup();
|
||||
// Perform the main setup for the demo
|
||||
setup();
|
||||
|
||||
//Begin the timer that will take readings of the coder at regular intervals
|
||||
struct repeating_timer timer;
|
||||
add_repeating_timer_us(-TIME_BETWEEN_SAMPLES_US, repeating_timer_callback, NULL, &timer);
|
||||
// Begin the timer that will take readings of the coder at regular intervals
|
||||
struct repeating_timer timer;
|
||||
add_repeating_timer_us(-TIME_BETWEEN_SAMPLES_US, repeating_timer_callback, NULL, &timer);
|
||||
|
||||
bool aPressedLatch = false;
|
||||
bool xPressedLatch = false;
|
||||
uint64_t last_time = time_us_64();
|
||||
bool aPressedLatch = false;
|
||||
bool xPressedLatch = false;
|
||||
uint64_t last_time = time_us_64();
|
||||
|
||||
while(true) {
|
||||
|
||||
//Has enough time elapsed since we last refreshed the screen?
|
||||
uint64_t current_time = time_us_64();
|
||||
if(current_time > last_time + MAIN_LOOP_TIME_US) {
|
||||
last_time = current_time;
|
||||
|
||||
gpio_put(PICO_DEFAULT_LED_PIN, true); //Show the screen refresh has stated
|
||||
while(true) {
|
||||
|
||||
//If the user has wired up their encoder switch, and it is pressed, set the encoder count to zero
|
||||
if(ENCODER_SWITCH_PIN != Encoder::PIN_UNUSED && gpio_get(ENCODER_SWITCH_PIN)) {
|
||||
encoder.zero_count();
|
||||
}
|
||||
// Has enough time elapsed since we last refreshed the screen?
|
||||
uint64_t current_time = time_us_64();
|
||||
if(current_time > last_time + MAIN_LOOP_TIME_US) {
|
||||
last_time = current_time;
|
||||
|
||||
//Take a capture, or snapshot of the current encoder state
|
||||
Capture capture = encoder.perform_capture();
|
||||
|
||||
//Spin Motor 1 either clockwise or counterclockwise depending on if B or Y are pressed
|
||||
if(pico_explorer.is_pressed(PicoExplorer::B) && !pico_explorer.is_pressed(PicoExplorer::Y))
|
||||
pico_explorer.set_motor(PicoExplorer::MOTOR1, PicoExplorer::FORWARD, 1.0f);
|
||||
else if(pico_explorer.is_pressed(PicoExplorer::Y) && !pico_explorer.is_pressed(PicoExplorer::B))
|
||||
pico_explorer.set_motor(PicoExplorer::MOTOR1, PicoExplorer::REVERSE, 0.2f);
|
||||
else
|
||||
pico_explorer.set_motor(PicoExplorer::MOTOR1, PicoExplorer::STOP);
|
||||
|
||||
gpio_put(PICO_DEFAULT_LED_PIN, true); // Show the screen refresh has stated
|
||||
|
||||
//If A has been pressed, zoom the view out to a min of x1
|
||||
if(pico_explorer.is_pressed(PicoExplorer::A)) {
|
||||
if(!aPressedLatch) {
|
||||
aPressedLatch = true;
|
||||
current_zoom_level = std::max(current_zoom_level / 2, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
aPressedLatch = false;
|
||||
}
|
||||
// If the user has wired up their encoder switch, and it is pressed, set the encoder count to zero
|
||||
if(ENCODER_SWITCH_PIN != Encoder::PIN_UNUSED && gpio_get(ENCODER_SWITCH_PIN)) {
|
||||
encoder.zero_count();
|
||||
}
|
||||
|
||||
//If X has been pressed, zoom the view in to the max of x512
|
||||
if(pico_explorer.is_pressed(PicoExplorer::X)) {
|
||||
if(!xPressedLatch) {
|
||||
xPressedLatch = true;
|
||||
current_zoom_level = std::min(current_zoom_level * 2, 512);
|
||||
}
|
||||
}
|
||||
else {
|
||||
xPressedLatch = false;
|
||||
}
|
||||
// Take a capture, or snapshot of the current encoder state
|
||||
Capture capture = encoder.perform_capture();
|
||||
|
||||
//--------------------------------------------------
|
||||
// Draw the encoder readings to the screen as a signal plot
|
||||
// Spin Motor 1 either clockwise or counterclockwise depending on if B or Y are pressed
|
||||
if(pico_explorer.is_pressed(PicoExplorer::B) && !pico_explorer.is_pressed(PicoExplorer::Y)) {
|
||||
pico_explorer.set_motor(PicoExplorer::MOTOR1, PicoExplorer::FORWARD, 1.0f);
|
||||
}
|
||||
else if(pico_explorer.is_pressed(PicoExplorer::Y) && !pico_explorer.is_pressed(PicoExplorer::B)) {
|
||||
pico_explorer.set_motor(PicoExplorer::MOTOR1, PicoExplorer::REVERSE, 0.2f);
|
||||
}
|
||||
else {
|
||||
pico_explorer.set_motor(PicoExplorer::MOTOR1, PicoExplorer::STOP);
|
||||
}
|
||||
|
||||
pico_explorer.set_pen(0, 0, 0);
|
||||
pico_explorer.clear();
|
||||
|
||||
drawing_to_screen = true;
|
||||
|
||||
pico_explorer.set_pen(255, 255, 0);
|
||||
uint32_t localPos = next_reading_index;
|
||||
uint32_t alignment_offset = draw_plot(Point(0, 10), Point(PicoExplorer::WIDTH, 10 + 50), encA_readings, localPos, current_zoom_level > EDGE_ALIGN_ABOVE_ZOOM);
|
||||
|
||||
pico_explorer.set_pen(0, 255, 255);
|
||||
draw_plot(Point(0, 80), Point(PicoExplorer::WIDTH, 80 + 50), encB_readings, (localPos + (READINGS_SIZE - alignment_offset)) % READINGS_SIZE, false);
|
||||
|
||||
//Copy values that may have been stored in the scratch buffers, back into the main buffers
|
||||
for(uint16_t i = 0; i < next_scratch_index; i++) {
|
||||
encA_readings[next_reading_index] = encA_scratch[i];
|
||||
encB_readings[next_reading_index] = encB_scratch[i];
|
||||
|
||||
next_reading_index++;
|
||||
if(next_reading_index >= READINGS_SIZE)
|
||||
next_reading_index = 0;
|
||||
}
|
||||
drawing_to_screen = false;
|
||||
next_scratch_index = 0;
|
||||
|
||||
pico_explorer.set_pen(255, 255, 255);
|
||||
pico_explorer.character('A', Point(5, 10 + 15), 3);
|
||||
pico_explorer.character('B', Point(5, 80 + 15), 3);
|
||||
|
||||
if(current_zoom_level < 10)
|
||||
pico_explorer.text("x" + std::to_string(current_zoom_level), Point(220, 62), 200, 2);
|
||||
else if(current_zoom_level < 100)
|
||||
pico_explorer.text("x" + std::to_string(current_zoom_level), Point(210, 62), 200, 2);
|
||||
else
|
||||
pico_explorer.text("x" + std::to_string(current_zoom_level), Point(200, 62), 200, 2);
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Write out the count, frequency and rpm of the encoder
|
||||
|
||||
pico_explorer.set_pen(8, 8, 8);
|
||||
pico_explorer.rectangle(Rect(0, 140, PicoExplorer::WIDTH, PicoExplorer::HEIGHT - 140));
|
||||
|
||||
pico_explorer.set_pen(64, 64, 64);
|
||||
pico_explorer.rectangle(Rect(0, 140, PicoExplorer::WIDTH, 2));
|
||||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << capture.get_count();
|
||||
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("Count:", Point(10, 150), 200, 3);
|
||||
pico_explorer.set_pen(255, 128, 255); pico_explorer.text(sstream.str(), Point(110, 150), 200, 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << std::fixed << std::setprecision(1) << capture.get_frequency() << "hz";
|
||||
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("Freq: ", Point(10, 180), 220, 3);
|
||||
pico_explorer.set_pen(128, 255, 255); pico_explorer.text(sstream.str(), Point(90, 180), 220, 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << std::fixed << std::setprecision(1) << capture.get_revolutions_per_minute();
|
||||
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("RPM: ", Point(10, 210), 220, 3);
|
||||
pico_explorer.set_pen(255, 255, 128); pico_explorer.text(sstream.str(), Point(80, 210), 220, 3);
|
||||
}
|
||||
|
||||
pico_explorer.update(); //Refresh the screen
|
||||
gpio_put(PICO_DEFAULT_LED_PIN, false); //Show the screen refresh has ended
|
||||
// If A has been pressed, zoom the view out to a min of x1
|
||||
if(pico_explorer.is_pressed(PicoExplorer::A)) {
|
||||
if(!aPressedLatch) {
|
||||
aPressedLatch = true;
|
||||
current_zoom_level = std::max(current_zoom_level / 2, 1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
aPressedLatch = false;
|
||||
}
|
||||
|
||||
// If X has been pressed, zoom the view in to the max of x512
|
||||
if(pico_explorer.is_pressed(PicoExplorer::X)) {
|
||||
if(!xPressedLatch) {
|
||||
xPressedLatch = true;
|
||||
current_zoom_level = std::min(current_zoom_level * 2, 512);
|
||||
}
|
||||
}
|
||||
else {
|
||||
xPressedLatch = false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------
|
||||
// Draw the encoder readings to the screen as a signal plot
|
||||
|
||||
pico_explorer.set_pen(0, 0, 0);
|
||||
pico_explorer.clear();
|
||||
|
||||
drawing_to_screen = true;
|
||||
|
||||
pico_explorer.set_pen(255, 255, 0);
|
||||
uint32_t localPos = next_reading_index;
|
||||
uint32_t alignment_offset = draw_plot(Point(0, 10), Point(PicoExplorer::WIDTH, 10 + 50), encA_readings, localPos, current_zoom_level > EDGE_ALIGN_ABOVE_ZOOM);
|
||||
|
||||
pico_explorer.set_pen(0, 255, 255);
|
||||
draw_plot(Point(0, 80), Point(PicoExplorer::WIDTH, 80 + 50), encB_readings, (localPos + (READINGS_SIZE - alignment_offset)) % READINGS_SIZE, false);
|
||||
|
||||
// Copy values that may have been stored in the scratch buffers, back into the main buffers
|
||||
for(uint16_t i = 0; i < next_scratch_index; i++) {
|
||||
encA_readings[next_reading_index] = encA_scratch[i];
|
||||
encB_readings[next_reading_index] = encB_scratch[i];
|
||||
|
||||
next_reading_index++;
|
||||
if(next_reading_index >= READINGS_SIZE)
|
||||
next_reading_index = 0;
|
||||
}
|
||||
|
||||
drawing_to_screen = false;
|
||||
next_scratch_index = 0;
|
||||
|
||||
pico_explorer.set_pen(255, 255, 255);
|
||||
pico_explorer.character('A', Point(5, 10 + 15), 3);
|
||||
pico_explorer.character('B', Point(5, 80 + 15), 3);
|
||||
|
||||
if(current_zoom_level < 10)
|
||||
pico_explorer.text("x" + std::to_string(current_zoom_level), Point(220, 62), 200, 2);
|
||||
else if(current_zoom_level < 100)
|
||||
pico_explorer.text("x" + std::to_string(current_zoom_level), Point(210, 62), 200, 2);
|
||||
else
|
||||
pico_explorer.text("x" + std::to_string(current_zoom_level), Point(200, 62), 200, 2);
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
// Write out the count, frequency and rpm of the encoder
|
||||
|
||||
pico_explorer.set_pen(8, 8, 8);
|
||||
pico_explorer.rectangle(Rect(0, 140, PicoExplorer::WIDTH, PicoExplorer::HEIGHT - 140));
|
||||
|
||||
pico_explorer.set_pen(64, 64, 64);
|
||||
pico_explorer.rectangle(Rect(0, 140, PicoExplorer::WIDTH, 2));
|
||||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << capture.get_count();
|
||||
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("Count:", Point(10, 150), 200, 3);
|
||||
pico_explorer.set_pen(255, 128, 255); pico_explorer.text(sstream.str(), Point(110, 150), 200, 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << std::fixed << std::setprecision(1) << capture.get_frequency() << "hz";
|
||||
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("Freq: ", Point(10, 180), 220, 3);
|
||||
pico_explorer.set_pen(128, 255, 255); pico_explorer.text(sstream.str(), Point(90, 180), 220, 3);
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream sstream;
|
||||
sstream << std::fixed << std::setprecision(1) << capture.get_revolutions_per_minute();
|
||||
pico_explorer.set_pen(255, 255, 255); pico_explorer.text("RPM: ", Point(10, 210), 220, 3);
|
||||
pico_explorer.set_pen(255, 255, 128); pico_explorer.text(sstream.str(), Point(80, 210), 220, 3);
|
||||
}
|
||||
|
||||
pico_explorer.update(); // Refresh the screen
|
||||
gpio_put(PICO_DEFAULT_LED_PIN, false); // Show the screen refresh has ended
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue