kopia lustrzana https://github.com/pimoroni/pimoroni-pico
				
				
				
			Encoder mostly implemented, now with MP support
							rodzic
							
								
									564fecf1de
								
							
						
					
					
						commit
						90fd4b8fb9
					
				|  | @ -1,70 +0,0 @@ | |||
| #include <math.h> | ||||
| #include <cfloat> | ||||
| #include "capture.hpp" | ||||
| 
 | ||||
| namespace pimoroni { | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   // CONSTRUCTORS
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   Capture::Capture(int32_t captured_count, int32_t count_change, float average_frequency, float counts_per_revolution) : | ||||
|     captured_count(captured_count), capture_count_change(count_change), average_frequency(average_frequency), | ||||
|     counts_per_revolution(MAX(counts_per_revolution, FLT_MIN)) { //Clamp counts_per_rev to avoid potential NaN
 | ||||
|   } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   // METHODS
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   int32_t Capture::count() const { | ||||
|     return captured_count; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::revolutions() const { | ||||
|     return (float)count() / counts_per_revolution; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::angle_degrees() const { | ||||
|     return revolutions() * 360.0f; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::angle_radians() const { | ||||
|     return revolutions() * M_TWOPI; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////  
 | ||||
|   int32_t Capture::count_change() const { | ||||
|     return capture_count_change; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::frequency() const { | ||||
|     return average_frequency; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::revolutions_per_second() const { | ||||
|     return frequency() / counts_per_revolution; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::revolutions_per_minute() const { | ||||
|     return revolutions_per_second() * 60.0f; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::degrees_per_second() const { | ||||
|     return revolutions_per_second() * 360.0f; | ||||
|   } | ||||
| 
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   float Capture::radians_per_second() const { | ||||
|     return revolutions_per_second() * M_TWOPI; | ||||
|   } | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
|   ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| } | ||||
|  | @ -1,45 +0,0 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include "pico/stdlib.h" | ||||
| 
 | ||||
| namespace pimoroni { | ||||
| 
 | ||||
|   class Capture { | ||||
|     //--------------------------------------------------
 | ||||
|     // Variables
 | ||||
|     //--------------------------------------------------
 | ||||
|   private: | ||||
|     const int32_t captured_count        = 0; | ||||
|     const int32_t capture_count_change  = 0; | ||||
|     const float average_frequency       = 0.0f; | ||||
|     const float counts_per_revolution   = 1; | ||||
| 
 | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
|     // Constructors
 | ||||
|     //--------------------------------------------------
 | ||||
|   public: | ||||
|     Capture() {} | ||||
|     Capture(int32_t captured_count, int32_t count_change, | ||||
|             float average_frequency, float counts_per_revolution); | ||||
| 
 | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
|     // Methods
 | ||||
|     //--------------------------------------------------
 | ||||
|   public: | ||||
|     int32_t count() const; | ||||
|     float revolutions() const; | ||||
|     float angle_degrees() const; | ||||
|     float angle_radians() const; | ||||
| 
 | ||||
|     int32_t count_change() const; | ||||
| 
 | ||||
|     float frequency() const; | ||||
|     float revolutions_per_second() const; | ||||
|     float revolutions_per_minute() const; | ||||
|     float degrees_per_second() const; | ||||
|     float radians_per_second() const; | ||||
|   }; | ||||
| 
 | ||||
| } | ||||
|  | @ -3,7 +3,6 @@ add_library(${DRIVER_NAME} INTERFACE) | |||
| 
 | ||||
| target_sources(${DRIVER_NAME} INTERFACE | ||||
|   ${CMAKE_CURRENT_LIST_DIR}/encoder.cpp | ||||
|   ${CMAKE_CURRENT_LIST_DIR}/capture.cpp | ||||
| ) | ||||
| 
 | ||||
| pico_generate_pio_header(${DRIVER_NAME} ${CMAKE_CURRENT_LIST_DIR}/encoder.pio) | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| #include <math.h> | ||||
| #include <cfloat> | ||||
| #include <climits> | ||||
| #include "hardware/irq.h" | ||||
| #include "encoder.hpp" | ||||
|  | @ -17,14 +18,63 @@ uint8_t Encoder::claimed_sms[] = { 0x0, 0x0 }; | |||
| uint Encoder::pio_program_offset[] = { 0, 0 }; | ||||
| 
 | ||||
| 
 | ||||
| Encoder::Encoder(PIO pio, uint sm, const pin_pair &pins, uint pin_c, | ||||
|                   float counts_per_revolution, bool count_microsteps, | ||||
|                   uint16_t freq_divider) | ||||
| Encoder::Snapshot::Snapshot() | ||||
| : count(0), delta(0), frequency(0.0f), counts_per_rev(INT32_MAX) { | ||||
| } | ||||
| 
 | ||||
| Encoder::Snapshot::Snapshot(int32_t count, int32_t delta, float frequency, float counts_per_rev) | ||||
| : count(count), delta(delta), frequency(frequency) | ||||
| , counts_per_rev(MAX(counts_per_rev, FLT_EPSILON)) { //Clamp counts_per_rev to avoid potential NaN
 | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::revolutions() const { | ||||
|   return (float)count / counts_per_rev; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::degrees() const { | ||||
|   return revolutions() * 360.0f; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::radians() const { | ||||
|   return revolutions() * M_TWOPI; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::revolutions_delta() const { | ||||
|   return (float)delta / counts_per_rev; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::degrees_delta() const { | ||||
|   return revolutions_delta() * 360.0f; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::radians_delta() const { | ||||
|   return revolutions_delta() * M_TWOPI; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::revolutions_per_second() const { | ||||
|   return frequency / counts_per_rev; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::revolutions_per_minute() const { | ||||
|   return revolutions_per_second() * 60.0f; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::degrees_per_second() const { | ||||
|   return revolutions_per_second() * 360.0f; | ||||
| } | ||||
| 
 | ||||
| float Encoder::Snapshot::radians_per_second() const { | ||||
|   return revolutions_per_second() * M_TWOPI; | ||||
| } | ||||
| 
 | ||||
| Encoder::Encoder(PIO pio, uint sm, const pin_pair &pins, uint common_pin, Direction direction, | ||||
|                   float counts_per_rev, bool count_microsteps, uint16_t freq_divider) | ||||
| : pio(pio) | ||||
| , sm(sm) | ||||
| , enc_pins(pins) | ||||
| , pin_c(pin_c) | ||||
| , counts_per_revolution(counts_per_revolution) | ||||
| , enc_common_pin(common_pin) | ||||
| , enc_direction(direction) | ||||
| , enc_counts_per_rev(MAX(counts_per_rev, FLT_EPSILON)) | ||||
| , count_microsteps(count_microsteps) | ||||
| , freq_divider(freq_divider) | ||||
| , clocks_per_time((float)(clock_get_hz(clk_sys) / (ENC_LOOP_CYCLES * freq_divider))) { | ||||
|  | @ -57,8 +107,8 @@ Encoder::~Encoder() { | |||
|     gpio_set_function(enc_pins.a, GPIO_FUNC_NULL); | ||||
|     gpio_set_function(enc_pins.b, GPIO_FUNC_NULL); | ||||
| 
 | ||||
|     if(pin_c != PIN_UNUSED) { | ||||
|       gpio_set_function(pin_c, GPIO_FUNC_NULL); | ||||
|     if(enc_common_pin != PIN_UNUSED) { | ||||
|       gpio_set_function(enc_common_pin, GPIO_FUNC_NULL); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -68,7 +118,7 @@ void Encoder::pio_interrupt_handler(uint pio_idx) { | |||
|   // and if there's an associated encoder, have it update its state
 | ||||
|   for(uint8_t sm = 0; sm < NUM_PIO_STATE_MACHINES; sm++) { | ||||
|     if(encoders[pio_idx][sm] != nullptr) { | ||||
|       encoders[pio_idx][sm]->check_for_transition();  | ||||
|       encoders[pio_idx][sm]->process_steps(); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | @ -87,10 +137,10 @@ bool Encoder::init() { | |||
|     if((enc_pins.a < NUM_BANK0_GPIOS) && (enc_pins.b < NUM_BANK0_GPIOS)) { | ||||
| 
 | ||||
|       // If a Pin C was defined, and valid, set it as a GND to pull the other two pins down
 | ||||
|       if((pin_c != PIN_UNUSED) && (pin_c < NUM_BANK0_GPIOS)) { | ||||
|         gpio_init(pin_c); | ||||
|         gpio_set_dir(pin_c, GPIO_OUT); | ||||
|         gpio_put(pin_c, false); | ||||
|       if((enc_common_pin != PIN_UNUSED) && (enc_common_pin < NUM_BANK0_GPIOS)) { | ||||
|         gpio_init(enc_common_pin); | ||||
|         gpio_set_dir(enc_common_pin, GPIO_OUT); | ||||
|         gpio_put(enc_common_pin, false); | ||||
|       } | ||||
| 
 | ||||
|       pio_sm_claim(pio, sm); | ||||
|  | @ -119,8 +169,6 @@ bool Encoder::init() { | |||
|       sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX); | ||||
| 
 | ||||
|       sm_config_set_clkdiv_int_frac(&c, freq_divider, 0); | ||||
|       //float div = clock_get_hz(clk_sys) / 500000;
 | ||||
|       //sm_config_set_clkdiv(&c, div);
 | ||||
| 
 | ||||
|       pio_sm_init(pio, sm, pio_program_offset[pio_idx], &c); | ||||
| 
 | ||||
|  | @ -157,92 +205,97 @@ pin_pair Encoder::pins() const { | |||
|   return enc_pins; | ||||
| } | ||||
| 
 | ||||
| uint Encoder::common_pin() const { | ||||
|   return enc_common_pin; | ||||
| } | ||||
| 
 | ||||
| bool_pair Encoder::state() const { | ||||
|   return bool_pair(enc_state_a, enc_state_b); | ||||
| } | ||||
| 
 | ||||
| int32_t Encoder::count() const { | ||||
|   return enc_count - count_offset; | ||||
|   return enc_count; | ||||
| } | ||||
| 
 | ||||
| int32_t Encoder::delta() { | ||||
|   int32_t count = enc_count;  // Store a local copy of enc_count to avoid two reads
 | ||||
| 
 | ||||
|   // Determine the change in counts since the last time this function was performed
 | ||||
|   int32_t change = count - last_count; | ||||
|   last_count = count; | ||||
| 
 | ||||
|   return change; | ||||
| } | ||||
| 
 | ||||
| void Encoder::zero() { | ||||
|   enc_count = 0; | ||||
|   enc_cumulative_time = 0; | ||||
|   enc_step = 0; | ||||
|   enc_turn = 0; | ||||
| 
 | ||||
|   microstep_time = 0; | ||||
|   step_dir = NO_DIR; // may not be wanted?
 | ||||
| 
 | ||||
|   last_count = 0; | ||||
|   last_snapshot_count = 0; | ||||
| } | ||||
| 
 | ||||
| int16_t Encoder::step() const { | ||||
|   return enc_step; | ||||
| } | ||||
| 
 | ||||
| int16_t Encoder::turn() const { | ||||
|   return enc_turn; | ||||
| } | ||||
| 
 | ||||
| float Encoder::revolutions() const { | ||||
|   return (float)count() / counts_per_revolution; | ||||
|   return (float)count() / enc_counts_per_rev; | ||||
| } | ||||
| 
 | ||||
| float Encoder::angle_degrees() const { | ||||
| float Encoder::degrees() const { | ||||
|   return revolutions() * 360.0f; | ||||
| } | ||||
| 
 | ||||
| float Encoder::angle_radians() const { | ||||
| float Encoder::radians() const { | ||||
|   return revolutions() * M_TWOPI; | ||||
| } | ||||
| 
 | ||||
| float Encoder::frequency() const { | ||||
|   return clocks_per_time / (float)time_since; | ||||
| Direction Encoder::direction() const { | ||||
|   return enc_direction; | ||||
| } | ||||
| 
 | ||||
| float Encoder::revolutions_per_second() const { | ||||
|   return frequency() / counts_per_revolution; | ||||
| void Encoder::direction(Direction direction) { | ||||
|   enc_direction = direction; | ||||
| } | ||||
| 
 | ||||
| float Encoder::revolutions_per_minute() const { | ||||
|   return revolutions_per_second() * 60.0f; | ||||
| float Encoder::counts_per_revolution() const { | ||||
|   return enc_counts_per_rev; | ||||
| } | ||||
| 
 | ||||
| float Encoder::degrees_per_second() const { | ||||
|   return revolutions_per_second() * 360.0f; | ||||
| void Encoder::counts_per_revolution(float counts_per_rev) { | ||||
|   enc_counts_per_rev = MAX(counts_per_rev, FLT_EPSILON); | ||||
| } | ||||
| 
 | ||||
| float Encoder::radians_per_second() const { | ||||
|   return revolutions_per_second() * M_TWOPI; | ||||
| } | ||||
| Encoder::Snapshot Encoder::take_snapshot() { | ||||
|   // Take a snapshot of the current values
 | ||||
|   int32_t count = enc_count; | ||||
|   int32_t cumulative_time = enc_cumulative_time; | ||||
|   enc_cumulative_time = 0; | ||||
| 
 | ||||
| void Encoder::zero_count() { | ||||
|   count_offset = enc_count; | ||||
| } | ||||
| 
 | ||||
| Capture Encoder::perform_capture() { | ||||
|   // Capture the current values
 | ||||
|   int32_t captured_count = enc_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 snapshot was taken
 | ||||
|   int32_t change = count - last_snapshot_count; | ||||
|   last_snapshot_count = count; | ||||
| 
 | ||||
|   // Calculate the average frequency of state transitions
 | ||||
|   float average_frequency = 0.0f; | ||||
|   if(count_change != 0 && captured_cumulative_time != INT_MAX) { | ||||
|     average_frequency = (clocks_per_time * (float)count_change) / (float)captured_cumulative_time; | ||||
|   float frequency = 0.0f; | ||||
|   if(change != 0 && cumulative_time != INT32_MAX) { | ||||
|     frequency = (clocks_per_time * (float)change) / (float)cumulative_time; | ||||
|   } | ||||
| 
 | ||||
|   return Capture(captured_count, count_change, average_frequency, counts_per_revolution); | ||||
|   return Snapshot(count, change, frequency, enc_counts_per_rev); | ||||
| } | ||||
| 
 | ||||
| void Encoder::microstep_up(int32_t time) { | ||||
|   enc_count++; | ||||
|   time_since = time; | ||||
|   microstep_time = 0; | ||||
| 
 | ||||
|   if(time + cumulative_time < time)  //Check to avoid integer overflow
 | ||||
|     cumulative_time = INT_MAX; | ||||
|   else | ||||
|     cumulative_time += time; | ||||
| } | ||||
| 
 | ||||
| void Encoder::microstep_down(int32_t time) { | ||||
|   enc_count--; | ||||
|   time_since = 0 - time; | ||||
|   microstep_time = 0; | ||||
| 
 | ||||
|   if(time + cumulative_time < time)  //Check to avoid integer overflow
 | ||||
|     cumulative_time = INT_MAX; | ||||
|   else | ||||
|     cumulative_time += time; | ||||
| } | ||||
| 
 | ||||
| void Encoder::check_for_transition() { | ||||
| void Encoder::process_steps() { | ||||
|   while(pio->ints1 & (PIO_IRQ1_INTS_SM0_RXNEMPTY_BITS << sm)) { | ||||
|     uint32_t received = pio_sm_get(pio, sm); | ||||
| 
 | ||||
|  | @ -264,6 +317,8 @@ void Encoder::check_for_transition() { | |||
|       microstep_time = time_received; | ||||
|     } | ||||
| 
 | ||||
|     bool up = (enc_direction == NORMAL); | ||||
| 
 | ||||
|     // Determine what transition occurred
 | ||||
|     switch(LAST_STATE(states)) { | ||||
|       //--------------------------------------------------
 | ||||
|  | @ -273,14 +328,14 @@ void Encoder::check_for_transition() { | |||
|           // B _________
 | ||||
|           case MICROSTEP_1: | ||||
|             if(count_microsteps) | ||||
|               microstep_up(time_received); | ||||
|               microstep(time_received, up); | ||||
|             break; | ||||
| 
 | ||||
|           // A _________
 | ||||
|           // B ____|‾‾‾‾
 | ||||
|           case MICROSTEP_3: | ||||
|             if(count_microsteps) | ||||
|               microstep_down(time_received); | ||||
|               microstep(time_received, !up); | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|  | @ -291,21 +346,21 @@ void Encoder::check_for_transition() { | |||
|           // A ‾‾‾‾‾‾‾‾‾
 | ||||
|           // B ____|‾‾‾‾
 | ||||
|           case MICROSTEP_2: | ||||
|             if(count_microsteps || last_travel_dir == CLOCKWISE) | ||||
|               microstep_up(time_received); | ||||
|             if(count_microsteps || step_dir == INCREASING) | ||||
|               microstep(time_received, up); | ||||
| 
 | ||||
|             last_travel_dir = NO_DIR;  // Finished turning clockwise
 | ||||
|             step_dir = NO_DIR;  // Finished increasing
 | ||||
|             break; | ||||
| 
 | ||||
|           // A ‾‾‾‾|____
 | ||||
|           // B _________
 | ||||
|           case MICROSTEP_0: | ||||
|             if(count_microsteps) | ||||
|               microstep_down(time_received); | ||||
|               microstep(time_received, !up); | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|          | ||||
| 
 | ||||
|       //--------------------------------------------------
 | ||||
|       case MICROSTEP_2: | ||||
|         switch(CURR_STATE(states)) { | ||||
|  | @ -313,18 +368,18 @@ void Encoder::check_for_transition() { | |||
|           // B ‾‾‾‾‾‾‾‾‾
 | ||||
|           case MICROSTEP_3: | ||||
|             if(count_microsteps) | ||||
|               microstep_up(time_received); | ||||
|              | ||||
|             last_travel_dir = CLOCKWISE;  // Started turning clockwise
 | ||||
|               microstep(time_received, up); | ||||
| 
 | ||||
|             step_dir = INCREASING;  // Started increasing
 | ||||
|             break; | ||||
| 
 | ||||
|           // A ‾‾‾‾‾‾‾‾‾
 | ||||
|           // B ‾‾‾‾|____
 | ||||
|           case MICROSTEP_1: | ||||
|             if(count_microsteps) | ||||
|               microstep_down(time_received); | ||||
|              | ||||
|             last_travel_dir = COUNTERCLOCK; // Started turning counter-clockwise
 | ||||
|               microstep(time_received, !up); | ||||
| 
 | ||||
|             step_dir = DECREASING;  // Started decreasing
 | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|  | @ -336,20 +391,43 @@ void Encoder::check_for_transition() { | |||
|           // B ‾‾‾‾|____
 | ||||
|           case MICROSTEP_0: | ||||
|             if(count_microsteps) | ||||
|               microstep_up(time_received); | ||||
|               microstep(time_received, up); | ||||
|             break; | ||||
| 
 | ||||
|           // A ____|‾‾‾‾
 | ||||
|           // B ‾‾‾‾‾‾‾‾‾
 | ||||
|           case MICROSTEP_2: | ||||
|             if(count_microsteps || last_travel_dir == COUNTERCLOCK) | ||||
|               microstep_down(time_received); | ||||
|             if(count_microsteps || step_dir == DECREASING) | ||||
|               microstep(time_received, !up); | ||||
| 
 | ||||
|             last_travel_dir = NO_DIR;    // Finished turning counter-clockwise
 | ||||
|             step_dir = NO_DIR;  // Finished decreasing
 | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void Encoder::microstep(int32_t time, bool up) { | ||||
|   if(up) { | ||||
|     enc_count++; | ||||
|     if(++enc_step >= (int16_t)enc_counts_per_rev) { | ||||
|       enc_step -= (int16_t)enc_counts_per_rev; | ||||
|       enc_turn++; | ||||
|     } | ||||
|   } | ||||
|   else { | ||||
|     enc_count--; | ||||
|     if(--enc_step < 0) { | ||||
|       enc_step += (int16_t)enc_counts_per_rev; | ||||
|       enc_turn--; | ||||
|     } | ||||
|   } | ||||
|   microstep_time = 0; | ||||
| 
 | ||||
|   if(time + enc_cumulative_time < time)  // Check to avoid integer overflow
 | ||||
|     enc_cumulative_time = INT32_MAX; | ||||
|   else | ||||
|     enc_cumulative_time += time; | ||||
| } | ||||
| } | ||||
|  | @ -2,10 +2,15 @@ | |||
| 
 | ||||
| #include "hardware/pio.h" | ||||
| #include "common/pimoroni_common.hpp" | ||||
| #include "capture.hpp" | ||||
| #include "snapshot.hpp" | ||||
| 
 | ||||
| namespace pimoroni { | ||||
| 
 | ||||
|   enum Direction { | ||||
|     NORMAL    = 0, | ||||
|     REVERSED  = 1, | ||||
|   }; | ||||
| 
 | ||||
|   struct bool_pair { | ||||
|     union { | ||||
|       bool first; | ||||
|  | @ -26,7 +31,7 @@ namespace pimoroni { | |||
|     //--------------------------------------------------
 | ||||
|   public: | ||||
|     static constexpr float DEFAULT_COUNTS_PER_REV   = 24; | ||||
|     static const uint16_t DEFAULT_COUNT_MICROSTEPS  = false; | ||||
|     static const bool DEFAULT_COUNT_MICROSTEPS      = false; | ||||
|     static const uint16_t DEFAULT_FREQ_DIVIDER      = 1; | ||||
| 
 | ||||
|   private: | ||||
|  | @ -40,20 +45,65 @@ namespace pimoroni { | |||
| 
 | ||||
|     static const uint32_t TIME_MASK   = 0x0fffffff; | ||||
| 
 | ||||
|     static const uint8_t MICROSTEP_0  = 0b00; | ||||
|     static const uint8_t MICROSTEP_1  = 0b10; | ||||
|     static const uint8_t MICROSTEP_2  = 0b11; | ||||
|     static const uint8_t MICROSTEP_3  = 0b01; | ||||
| 
 | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
|     // Enums
 | ||||
|     //--------------------------------------------------
 | ||||
|   private: | ||||
|     enum Direction { | ||||
|       NO_DIR        = 0, | ||||
|       CLOCKWISE     = 1, | ||||
|       COUNTERCLOCK  = -1, | ||||
|     enum StepDir { | ||||
|       NO_DIR    = 0, | ||||
|       INCREASING = 1, | ||||
|       DECREASING = -1, | ||||
|     }; | ||||
| 
 | ||||
|     enum MicroStep : uint8_t { | ||||
|       MICROSTEP_0 = 0b00, | ||||
|       MICROSTEP_1 = 0b10, | ||||
|       MICROSTEP_2 = 0b11, | ||||
|       MICROSTEP_3 = 0b01, | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
|     // Substructures
 | ||||
|     //--------------------------------------------------
 | ||||
|   public: | ||||
|     class Snapshot { | ||||
|         //--------------------------------------------------
 | ||||
|         // Variables
 | ||||
|         //--------------------------------------------------
 | ||||
|       public: | ||||
|         const int32_t count; | ||||
|         const int32_t delta; | ||||
|         const float frequency; | ||||
|       private: | ||||
|         float counts_per_rev; | ||||
| 
 | ||||
| 
 | ||||
|         //--------------------------------------------------
 | ||||
|         // Constructors
 | ||||
|         //--------------------------------------------------
 | ||||
|       public: | ||||
|         Snapshot(); | ||||
|         Snapshot(int32_t count, int32_t delta, float frequency, float counts_per_rev); | ||||
| 
 | ||||
| 
 | ||||
|         //--------------------------------------------------
 | ||||
|         // Methods
 | ||||
|         //--------------------------------------------------
 | ||||
|       public: | ||||
|         float revolutions() const; | ||||
|         float degrees() const; | ||||
|         float radians() const; | ||||
| 
 | ||||
|         float revolutions_delta() const; | ||||
|         float degrees_delta() const; | ||||
|         float radians_delta() const; | ||||
| 
 | ||||
|         float revolutions_per_second() const; | ||||
|         float revolutions_per_minute() const; | ||||
|         float degrees_per_second() const; | ||||
|         float radians_per_second() const; | ||||
|     }; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -64,27 +114,30 @@ namespace pimoroni { | |||
|     PIO pio; | ||||
|     uint sm; | ||||
|     pin_pair enc_pins; | ||||
|     uint pin_c; | ||||
|     uint enc_common_pin; | ||||
|     Direction enc_direction; | ||||
|     float enc_counts_per_rev; | ||||
| 
 | ||||
|     const float counts_per_revolution   = DEFAULT_COUNTS_PER_REV; | ||||
|     const bool count_microsteps         = DEFAULT_COUNT_MICROSTEPS; | ||||
|     const uint16_t freq_divider         = DEFAULT_FREQ_DIVIDER; | ||||
|     const float clocks_per_time         = 0; | ||||
|     const bool count_microsteps; | ||||
|     const uint16_t freq_divider; | ||||
|     const float clocks_per_time; | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
| 
 | ||||
|     volatile bool enc_state_a           = false; | ||||
|     volatile bool enc_state_b           = false; | ||||
|     volatile int32_t enc_count          = 0; | ||||
|     volatile int32_t time_since         = 0; | ||||
|     volatile Direction last_travel_dir  = NO_DIR; | ||||
|     volatile int32_t microstep_time     = 0; | ||||
|     volatile int32_t cumulative_time    = 0; | ||||
|     volatile bool enc_state_a             = false; | ||||
|     volatile bool enc_state_b             = false; | ||||
|     volatile int32_t enc_count            = 0; | ||||
|     volatile int32_t enc_cumulative_time  = 0; | ||||
|     volatile int16_t enc_step             = 0; | ||||
|     volatile int16_t enc_turn             = 0; | ||||
| 
 | ||||
|     int32_t count_offset                = 0; | ||||
|     int32_t last_captured_count         = 0; | ||||
|     volatile int32_t microstep_time       = 0; | ||||
|     volatile StepDir step_dir             = NO_DIR; | ||||
| 
 | ||||
|     bool initialised = false; | ||||
|     int32_t last_count                    = 0; | ||||
|     int32_t last_snapshot_count           = 0; | ||||
| 
 | ||||
|     bool initialised                      = false; | ||||
| 
 | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
|  | @ -102,9 +155,8 @@ namespace pimoroni { | |||
|     // Constructors/Destructor
 | ||||
|     //--------------------------------------------------
 | ||||
|   public: | ||||
|     Encoder() {} | ||||
|     Encoder(PIO pio, uint sm, const pin_pair &pins, uint pin_c = PIN_UNUSED, | ||||
|             float counts_per_revolution = DEFAULT_COUNTS_PER_REV, bool count_microsteps = DEFAULT_COUNT_MICROSTEPS, | ||||
|     Encoder(PIO pio, uint sm, const pin_pair &pins, uint common_pin = PIN_UNUSED, Direction direction = NORMAL, | ||||
|             float counts_per_rev = DEFAULT_COUNTS_PER_REV, bool count_microsteps = DEFAULT_COUNT_MICROSTEPS, | ||||
|             uint16_t freq_divider = DEFAULT_FREQ_DIVIDER); | ||||
|     ~Encoder(); | ||||
| 
 | ||||
|  | @ -117,26 +169,34 @@ namespace pimoroni { | |||
| 
 | ||||
|     // For print access in micropython
 | ||||
|     pin_pair pins() const; | ||||
|     uint common_pin() const; | ||||
| 
 | ||||
|     bool_pair state() const; | ||||
|     int32_t count() const; | ||||
|     int32_t delta(); | ||||
|     void zero(); | ||||
| 
 | ||||
|     int16_t step() const; | ||||
|     int16_t turn() const; | ||||
| 
 | ||||
|     float revolutions() const; | ||||
|     float angle_degrees() const; | ||||
|     float angle_radians() const; | ||||
|     float degrees() const; | ||||
|     float radians() const; | ||||
| 
 | ||||
|     float frequency() const; | ||||
|     float revolutions_per_second() const; | ||||
|     float revolutions_per_minute() const; | ||||
|     float degrees_per_second() const; | ||||
|     float radians_per_second() const; | ||||
|      | ||||
|     void zero_count(); | ||||
|     Capture perform_capture(); //TODO rename capture to snapshot
 | ||||
|     //--------------------------------------------------
 | ||||
| 
 | ||||
|     Direction direction() const; | ||||
|     void direction(Direction direction); | ||||
| 
 | ||||
|     float counts_per_revolution() const; | ||||
|     void counts_per_revolution(float counts_per_rev); | ||||
| 
 | ||||
|     Snapshot take_snapshot(); | ||||
| 
 | ||||
|     //--------------------------------------------------
 | ||||
|   private: | ||||
|     void microstep_up(int32_t time_since); | ||||
|     void microstep_down(int32_t time_since); | ||||
|     void check_for_transition(); | ||||
|     void process_steps(); | ||||
|     void microstep(int32_t time_since, bool up); | ||||
|   }; | ||||
| 
 | ||||
| } | ||||
|  | @ -54,7 +54,7 @@ enum DrawState { | |||
| uint16_t buffer[PicoExplorer::WIDTH * PicoExplorer::HEIGHT]; | ||||
| PicoExplorer pico_explorer(buffer); | ||||
| 
 | ||||
| Encoder encoder(pio0, 0, ENCODER_PINS, ENCODER_PIN_C, COUNTS_PER_REVOLUTION, COUNT_MICROSTEPS, FREQ_DIVIDER); | ||||
| Encoder encoder(pio0, 0, ENCODER_PINS, ENCODER_PIN_C, NORMAL, COUNTS_PER_REVOLUTION, COUNT_MICROSTEPS, FREQ_DIVIDER); | ||||
| 
 | ||||
| volatile bool encA_readings[READINGS_SIZE]; | ||||
| volatile bool encB_readings[READINGS_SIZE]; | ||||
|  | @ -226,11 +226,11 @@ int main() { | |||
| 
 | ||||
|       // If the user has wired up their encoder switch, and it is pressed, set the encoder count to zero
 | ||||
|       if(ENCODER_SWITCH_PIN != PIN_UNUSED && gpio_get(ENCODER_SWITCH_PIN)) { | ||||
|         encoder.zero_count(); | ||||
|         encoder.zero(); | ||||
|       } | ||||
| 
 | ||||
|       // Take a capture, or snapshot of the current encoder state
 | ||||
|       Capture capture = encoder.perform_capture(); | ||||
|       // Take a snapshot of the current encoder state
 | ||||
|       Encoder::Snapshot snapshot = encoder.take_snapshot(); | ||||
| 
 | ||||
|       // 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)) { | ||||
|  | @ -316,21 +316,21 @@ int main() { | |||
| 
 | ||||
|       { | ||||
|         std::stringstream sstream; | ||||
|         sstream << capture.count(); | ||||
|         sstream << snapshot.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.frequency() << "hz"; | ||||
|         sstream << std::fixed << std::setprecision(1) << snapshot.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.revolutions_per_minute(); | ||||
|         sstream << std::fixed << std::setprecision(1) << snapshot.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); | ||||
|       } | ||||
|  |  | |||
|  | @ -2,42 +2,85 @@ | |||
| 
 | ||||
| 
 | ||||
| /***** Methods *****/ | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot___del___obj, Snapshot___del__); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_count_obj, Snapshot_count); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_delta_obj, Snapshot_delta); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_frequency_obj, Snapshot_frequency); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_obj, Snapshot_revolutions); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_degrees_obj, Snapshot_degrees); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_radians_obj, Snapshot_radians); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_delta_obj, Snapshot_revolutions_delta); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_degrees_delta_obj, Snapshot_degrees_delta); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_radians_delta_obj, Snapshot_radians_delta); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_per_second_obj, Snapshot_revolutions_per_second); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_revolutions_per_minute_obj, Snapshot_revolutions_per_minute); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_degrees_per_second_obj, Snapshot_degrees_per_second); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Snapshot_radians_per_second_obj, Snapshot_radians_per_second); | ||||
| 
 | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder___del___obj, Encoder___del__); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_pins_obj, Encoder_pins); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_common_pin_obj, Encoder_common_pin); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_state_obj, Encoder_state); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_count_obj, Encoder_count); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_delta_obj, Encoder_delta); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_zero_obj, Encoder_zero); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_step_obj, Encoder_step); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_turn_obj, Encoder_turn); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_obj, Encoder_revolutions); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_degrees_obj, Encoder_angle_degrees); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_angle_radians_obj, Encoder_angle_radians); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_frequency_obj, Encoder_frequency); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_second_obj, Encoder_revolutions_per_second); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_revolutions_per_minute_obj, Encoder_revolutions_per_minute); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_degrees_per_second_obj, Encoder_degrees_per_second); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_radians_per_second_obj, Encoder_radians_per_second); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_zero_count_obj, Encoder_zero_count); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_degrees_obj, Encoder_degrees); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_radians_obj, Encoder_radians); | ||||
| MP_DEFINE_CONST_FUN_OBJ_KW(Encoder_direction_obj, 1, Encoder_direction); | ||||
| MP_DEFINE_CONST_FUN_OBJ_KW(Encoder_counts_per_revolution_obj, 1, Encoder_counts_per_revolution); | ||||
| MP_DEFINE_CONST_FUN_OBJ_1(Encoder_take_snapshot_obj, Encoder_take_snapshot); | ||||
| 
 | ||||
| /***** Binding of Methods *****/ | ||||
| STATIC const mp_rom_map_elem_t Snapshot_locals_dict_table[] = { | ||||
|     { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Snapshot___del___obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&Snapshot_count_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_delta), MP_ROM_PTR(&Snapshot_delta_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Snapshot_frequency_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions), MP_ROM_PTR(&Snapshot_revolutions_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&Snapshot_degrees_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&Snapshot_radians_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions_delta), MP_ROM_PTR(&Snapshot_revolutions_delta_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_degrees_delta), MP_ROM_PTR(&Snapshot_degrees_delta_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_radians_delta), MP_ROM_PTR(&Snapshot_radians_delta_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions_per_second), MP_ROM_PTR(&Snapshot_revolutions_per_second_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions_per_minute), MP_ROM_PTR(&Snapshot_revolutions_per_minute_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_degrees_per_second), MP_ROM_PTR(&Snapshot_degrees_per_second_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_radians_per_second), MP_ROM_PTR(&Snapshot_radians_per_second_obj) }, | ||||
| }; | ||||
| 
 | ||||
| STATIC const mp_rom_map_elem_t Encoder_locals_dict_table[] = { | ||||
|     { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Encoder___del___obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_pins), MP_ROM_PTR(&Encoder_pins_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_common_pin), MP_ROM_PTR(&Encoder_common_pin_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_state), MP_ROM_PTR(&Encoder_state_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_count), MP_ROM_PTR(&Encoder_count_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_delta), MP_ROM_PTR(&Encoder_delta_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_zero), MP_ROM_PTR(&Encoder_zero_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_step), MP_ROM_PTR(&Encoder_step_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_turn), MP_ROM_PTR(&Encoder_turn_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions), MP_ROM_PTR(&Encoder_revolutions_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_angle_degrees), MP_ROM_PTR(&Encoder_angle_degrees_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_angle_radians), MP_ROM_PTR(&Encoder_angle_radians_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_frequency), MP_ROM_PTR(&Encoder_frequency_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions_per_second), MP_ROM_PTR(&Encoder_revolutions_per_second_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_revolutions_per_minute), MP_ROM_PTR(&Encoder_revolutions_per_minute_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_degrees_per_second), MP_ROM_PTR(&Encoder_degrees_per_second_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_radians_per_second), MP_ROM_PTR(&Encoder_radians_per_second_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_zero_count), MP_ROM_PTR(&Encoder_zero_count_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_degrees), MP_ROM_PTR(&Encoder_degrees_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_radians), MP_ROM_PTR(&Encoder_radians_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_direction), MP_ROM_PTR(&Encoder_direction_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_counts_per_revolution), MP_ROM_PTR(&Encoder_counts_per_revolution_obj) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_take_snapshot), MP_ROM_PTR(&Encoder_take_snapshot_obj) }, | ||||
| }; | ||||
| 
 | ||||
| STATIC MP_DEFINE_CONST_DICT(Snapshot_locals_dict, Snapshot_locals_dict_table); | ||||
| STATIC MP_DEFINE_CONST_DICT(Encoder_locals_dict, Encoder_locals_dict_table); | ||||
| 
 | ||||
| /***** Class Definition *****/ | ||||
| const mp_obj_type_t Snapshot_type = { | ||||
|     { &mp_type_type }, | ||||
|     .name = MP_QSTR_snapshot, | ||||
|     .print = Snapshot_print, | ||||
|     .make_new = Snapshot_make_new, | ||||
|     .locals_dict = (mp_obj_dict_t*)&Snapshot_locals_dict, | ||||
| }; | ||||
| 
 | ||||
| const mp_obj_type_t Encoder_type = { | ||||
|     { &mp_type_type }, | ||||
|     .name = MP_QSTR_encoder, | ||||
|  | @ -50,10 +93,10 @@ const mp_obj_type_t Encoder_type = { | |||
| STATIC const mp_map_elem_t encoder_globals_table[] = { | ||||
|     { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_encoder) }, | ||||
|     { MP_OBJ_NEW_QSTR(MP_QSTR_Encoder), (mp_obj_t)&Encoder_type }, | ||||
|     { MP_OBJ_NEW_QSTR(MP_QSTR_Snapshot), (mp_obj_t)&Snapshot_type }, | ||||
| 
 | ||||
|     { MP_ROM_QSTR(MP_QSTR_ANGULAR), MP_ROM_INT(0x00) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_LINEAR), MP_ROM_INT(0x01) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_CONTINUOUS), MP_ROM_INT(0x02) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(0x00) }, | ||||
|     { MP_ROM_QSTR(MP_QSTR_REVERSED), MP_ROM_INT(0x01) }, | ||||
| }; | ||||
| STATIC MP_DEFINE_CONST_DICT(mp_module_encoder_globals, encoder_globals_table); | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| #include "drivers/encoder-pio/capture.hpp" | ||||
| #include "drivers/encoder-pio/encoder.hpp" | ||||
| #include <cstdio> | ||||
| #include <cfloat> | ||||
| 
 | ||||
| #define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o)) | ||||
| 
 | ||||
|  | @ -12,6 +12,112 @@ extern "C" { | |||
| #include "py/builtin.h" | ||||
| 
 | ||||
| 
 | ||||
| /********** Snapshot **********/ | ||||
| 
 | ||||
| /***** Variables Struct *****/ | ||||
| typedef struct _Snapshot_obj_t { | ||||
|     mp_obj_base_t base; | ||||
|     Encoder::Snapshot *snapshot; | ||||
| } _Snapshot_obj_t; | ||||
| 
 | ||||
| 
 | ||||
| /***** Print *****/ | ||||
| void Snapshot_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { | ||||
|     (void)kind; //Unused input parameter
 | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     Encoder::Snapshot* snap = self->snapshot; | ||||
|     mp_print_str(print, "Snapshot(count = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_int(snap->count), PRINT_REPR); | ||||
|     mp_print_str(print, ", delta = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_int(snap->delta), PRINT_REPR); | ||||
|     mp_print_str(print, ", freq = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_float(snap->frequency), PRINT_REPR); | ||||
|     mp_print_str(print, ")"); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***** Constructor *****/ | ||||
| mp_obj_t Snapshot_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { | ||||
|     mp_raise_TypeError("cannot create an instance of Snapshot. They can only be created by calling take_snapshot on an Encoder object"); | ||||
|     return mp_const_none; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***** Destructor ******/ | ||||
| mp_obj_t Snapshot___del__(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     delete self->snapshot; | ||||
|     return mp_const_none; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /***** Methods *****/ | ||||
| mp_obj_t Snapshot_count(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->count); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_delta(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->delta); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_frequency(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_float(self->snapshot->frequency); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_revolutions(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->revolutions()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_degrees(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->degrees()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_radians(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->radians()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_revolutions_delta(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->revolutions_delta()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_degrees_delta(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->degrees_delta()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_radians_delta(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_int(self->snapshot->radians_delta()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_revolutions_per_second(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_float(self->snapshot->revolutions_per_second()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_revolutions_per_minute(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_float(self->snapshot->revolutions_per_minute()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_degrees_per_second(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_float(self->snapshot->degrees_per_second()); | ||||
| } | ||||
| 
 | ||||
| mp_obj_t Snapshot_radians_per_second(mp_obj_t self_in) { | ||||
|     _Snapshot_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Snapshot_obj_t); | ||||
|     return mp_obj_new_float(self->snapshot->radians_per_second()); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /********** Encoder **********/ | ||||
| 
 | ||||
| /***** Variables Struct *****/ | ||||
|  | @ -32,15 +138,17 @@ void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki | |||
|     mp_obj_print_helper(print, mp_obj_new_int(pins.a), PRINT_REPR); | ||||
|     mp_print_str(print, ", "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_int(pins.b), PRINT_REPR); | ||||
|     mp_print_str(print, "), enabled = "); | ||||
|     /*mp_obj_print_helper(print, self->encoder->is_enabled() ? mp_const_true : mp_const_false, PRINT_REPR);
 | ||||
|     mp_print_str(print, ", pulse = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_float(self->encoder->pulse()), PRINT_REPR); | ||||
|     mp_print_str(print, ", value = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_float(self->encoder->value()), PRINT_REPR); | ||||
|     mp_print_str(print, ", freq = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_float(self->encoder->frequency()), PRINT_REPR); | ||||
| */ | ||||
|     mp_print_str(print, ", "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_int(self->encoder->common_pin()), PRINT_REPR); | ||||
|     mp_print_str(print, ")"); | ||||
| 
 | ||||
|     if(self->encoder->direction() == NORMAL) | ||||
|         mp_print_str(print, ", direction = NORMAL"); | ||||
|     else | ||||
|         mp_print_str(print, ", direction = REVERSED"); | ||||
| 
 | ||||
|     mp_print_str(print, ", counts_per_rev = "); | ||||
|     mp_obj_print_helper(print, mp_obj_new_float(self->encoder->counts_per_revolution()), PRINT_REPR); | ||||
|     mp_print_str(print, ")"); | ||||
| } | ||||
| 
 | ||||
|  | @ -49,14 +157,14 @@ void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki | |||
| mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { | ||||
|     _Encoder_obj_t *self = nullptr; | ||||
| 
 | ||||
|     enum { ARG_pio, ARG_sm, ARG_pins, ARG_pin_c, ARG_calibration, ARG_freq }; | ||||
|     enum { ARG_pio, ARG_sm, ARG_pins, ARG_common_pin, ARG_count_microsteps, ARG_freq_divider }; | ||||
|     static const mp_arg_t allowed_args[] = { | ||||
|         { MP_QSTR_pio, MP_ARG_REQUIRED | MP_ARG_INT }, | ||||
|         { MP_QSTR_sm, MP_ARG_REQUIRED | MP_ARG_INT }, | ||||
|         { MP_QSTR_pins, MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||||
|         { MP_QSTR_pin_c, MP_ARG_INT, {.u_int = PIN_UNUSED} }, | ||||
|         { MP_QSTR_calibration, MP_ARG_OBJ, {.u_obj = mp_const_none} }, | ||||
|         { MP_QSTR_freq, MP_ARG_OBJ, {.u_obj = mp_const_none} }, | ||||
|         { MP_QSTR_common_pin, MP_ARG_INT, {.u_int = PIN_UNUSED} }, | ||||
|         { MP_QSTR_count_microsteps, MP_ARG_BOOL, {.u_bool = false} }, | ||||
|         { MP_QSTR_freq_divider, MP_ARG_OBJ, {.u_obj = mp_const_none} }, | ||||
|     }; | ||||
| 
 | ||||
|     // Parse args.
 | ||||
|  | @ -101,33 +209,15 @@ mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, | |||
|         pins.a = (uint8_t)a; | ||||
|         pins.b = (uint8_t)b; | ||||
|     } | ||||
| /*
 | ||||
|     encoder::Calibration *calib = nullptr; | ||||
|     encoder::CalibrationType calibration_type = encoder::CalibrationType::ANGULAR; | ||||
|     const mp_obj_t calib_object = args[ARG_calibration].u_obj; | ||||
|     if(calib_object != mp_const_none) { | ||||
|         if(mp_obj_is_int(calib_object)) { | ||||
|             int type = mp_obj_get_int(calib_object); | ||||
|             if(type < 0 || type >= 3) { | ||||
|                 mp_raise_ValueError("type out of range. Expected ANGULAR (0), LINEAR (1) or CONTINUOUS (2)"); | ||||
|             } | ||||
|             calibration_type = (encoder::CalibrationType)type; | ||||
|         } | ||||
|         else if(mp_obj_is_type(calib_object, &Calibration_type)) { | ||||
|             calib = (MP_OBJ_TO_PTR2(calib_object, _Calibration_obj_t)->calibration); | ||||
|         } | ||||
|         else { | ||||
|             mp_raise_TypeError("cannot convert object to an integer or a Calibration class instance"); | ||||
|         } | ||||
| 
 | ||||
|     float freq_divider = Encoder::DEFAULT_FREQ_DIVIDER; | ||||
|     if(args[ARG_freq_divider].u_obj != mp_const_none) { | ||||
|         freq_divider = mp_obj_get_float(args[ARG_freq_divider].u_obj); | ||||
|     } | ||||
| 
 | ||||
|     float freq = encoder::EncoderState::DEFAULT_FREQUENCY; | ||||
|     if(args[ARG_freq].u_obj != mp_const_none) { | ||||
|         freq = mp_obj_get_float(args[ARG_freq].u_obj); | ||||
|     } | ||||
| */ | ||||
|     bool count_microsteps = args[ARG_count_microsteps].u_bool; | ||||
| 
 | ||||
|     Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_pin_c].u_int); | ||||
|     Encoder *encoder = new Encoder(pio, sm, pins, args[ARG_common_pin].u_int, NORMAL, Encoder::DEFAULT_COUNTS_PER_REV, count_microsteps, freq_divider); | ||||
|     if(!encoder->init()) { | ||||
|         delete encoder; | ||||
|         mp_raise_msg(&mp_type_RuntimeError, "unable to allocate the hardware resources needed to initialise this Encoder. Try running `import gc` followed by `gc.collect()` before creating it"); | ||||
|  | @ -160,6 +250,12 @@ extern mp_obj_t Encoder_pins(mp_obj_t self_in) { | |||
|     return mp_obj_new_tuple(2, tuple); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_common_pin(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_int(self->encoder->common_pin()); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| extern mp_obj_t Encoder_state(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     bool_pair state = self->encoder->state(); | ||||
|  | @ -175,55 +271,124 @@ extern mp_obj_t Encoder_count(mp_obj_t self_in) { | |||
|     return mp_obj_new_int(self->encoder->count()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_delta(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_int(self->encoder->delta()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_zero(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     self->encoder->zero(); | ||||
|     return mp_const_none; | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_step(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_int(self->encoder->step()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_turn(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_int(self->encoder->turn()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_revolutions(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->revolutions()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in) { | ||||
| extern mp_obj_t Encoder_degrees(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->angle_degrees()); | ||||
|     return mp_obj_new_float(self->encoder->degrees()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in) { | ||||
| extern mp_obj_t Encoder_radians(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->angle_radians()); | ||||
|     return mp_obj_new_float(self->encoder->radians()); | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_frequency(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->frequency()); | ||||
| extern mp_obj_t Encoder_direction(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { | ||||
|     if(n_args <= 1) { | ||||
|         enum { ARG_self }; | ||||
|         static const mp_arg_t allowed_args[] = { | ||||
|             { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||||
|         }; | ||||
| 
 | ||||
|         // Parse args.
 | ||||
|         mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; | ||||
|         mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); | ||||
| 
 | ||||
|         _Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t); | ||||
| 
 | ||||
|         return mp_obj_new_int(self->encoder->direction()); | ||||
|     } | ||||
|     else { | ||||
|         enum { ARG_self, ARG_direction }; | ||||
|         static const mp_arg_t allowed_args[] = { | ||||
|             { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||||
|             { MP_QSTR_direction, MP_ARG_REQUIRED | MP_ARG_INT }, | ||||
|         }; | ||||
| 
 | ||||
|         // Parse args.
 | ||||
|         mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; | ||||
|         mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); | ||||
| 
 | ||||
|         _Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t); | ||||
| 
 | ||||
|         int direction = args[ARG_direction].u_int; | ||||
|         if(direction < 0 || direction > 1) { | ||||
|             mp_raise_ValueError("direction out of range. Expected NORMAL (0) or REVERSED (1)"); | ||||
|         } | ||||
|         self->encoder->direction((Direction)direction); | ||||
|         return mp_const_none; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_revolutions_per_second(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->revolutions_per_second()); | ||||
| } | ||||
| extern mp_obj_t Encoder_counts_per_revolution(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { | ||||
|     if(n_args <= 1) { | ||||
|         enum { ARG_self }; | ||||
|         static const mp_arg_t allowed_args[] = { | ||||
|             { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||||
|         }; | ||||
| 
 | ||||
| extern mp_obj_t Encoder_revolutions_per_minute(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->revolutions_per_minute()); | ||||
| } | ||||
|         // Parse args.
 | ||||
|         mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; | ||||
|         mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); | ||||
| 
 | ||||
| extern mp_obj_t Encoder_degrees_per_second(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->degrees_per_second()); | ||||
| } | ||||
|         _Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t); | ||||
| 
 | ||||
| extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     return mp_obj_new_float(self->encoder->radians_per_second()); | ||||
| } | ||||
|         return mp_obj_new_float(self->encoder->counts_per_revolution()); | ||||
|     } | ||||
|     else { | ||||
|         enum { ARG_self, ARG_counts_per_rev }; | ||||
|         static const mp_arg_t allowed_args[] = { | ||||
|             { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||||
|             { MP_QSTR_counts_per_rev, MP_ARG_REQUIRED | MP_ARG_OBJ }, | ||||
|         }; | ||||
| 
 | ||||
| extern mp_obj_t Encoder_zero_count(mp_obj_t self_in) { | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
|     self->encoder->zero_count(); | ||||
|     return mp_const_none; | ||||
|         // Parse args.
 | ||||
|         mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; | ||||
|         mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); | ||||
| 
 | ||||
|         _Encoder_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self].u_obj, _Encoder_obj_t); | ||||
| 
 | ||||
|         float counts_per_rev = mp_obj_get_float(args[ARG_counts_per_rev].u_obj); | ||||
|         if(counts_per_rev < FLT_EPSILON) { | ||||
|             mp_raise_ValueError("counts_per_rev out of range. Expected greater than 0.0"); | ||||
|         } | ||||
|         self->encoder->counts_per_revolution(counts_per_rev); | ||||
|         return mp_const_none; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| extern mp_obj_t Encoder_take_snapshot(mp_obj_t self_in) { | ||||
|     //_Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t);
 | ||||
|     //Capture capture = self->encoder->perform_capture();
 | ||||
|     return mp_const_none; | ||||
|     _Encoder_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Encoder_obj_t); | ||||
| 
 | ||||
|     // Create a new MP Snapshot instance and assign a copy of the encoder's snapshot to it
 | ||||
|     _Snapshot_obj_t *snap = m_new_obj_with_finaliser(_Snapshot_obj_t); | ||||
|     snap->base.type = &Snapshot_type; | ||||
| 
 | ||||
|     snap->snapshot = new Encoder::Snapshot(self->encoder->take_snapshot()); | ||||
|     return MP_OBJ_FROM_PTR(snap); | ||||
| } | ||||
| } | ||||
|  |  | |||
|  | @ -2,22 +2,41 @@ | |||
| #include "py/runtime.h" | ||||
| 
 | ||||
| /***** Extern of Class Definition *****/ | ||||
| extern const mp_obj_type_t Snapshot_type; | ||||
| extern const mp_obj_type_t Encoder_type; | ||||
| 
 | ||||
| /***** Extern of Class Methods *****/ | ||||
| extern void Snapshot_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); | ||||
| extern mp_obj_t Snapshot_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); | ||||
| extern mp_obj_t Snapshot___del__(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_count(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_delta(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_frequency(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_revolutions(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_degrees(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_radians(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_revolutions_delta(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_degrees_delta(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_radians_delta(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_revolutions_per_second(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_revolutions_per_minute(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_degrees_per_second(mp_obj_t self_in); | ||||
| extern mp_obj_t Snapshot_radians_per_second(mp_obj_t self_in); | ||||
| 
 | ||||
| extern void Encoder_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); | ||||
| extern mp_obj_t Encoder_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args); | ||||
| extern mp_obj_t Encoder___del__(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_pins(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_common_pin(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_state(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_count(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_delta(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_zero(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_step(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_turn(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_revolutions(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_angle_degrees(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_angle_radians(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_frequency(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_revolutions_per_second(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_revolutions_per_minute(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_degrees_per_second(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_radians_per_second(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_zero_count(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_degrees(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_radians(mp_obj_t self_in); | ||||
| extern mp_obj_t Encoder_direction(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); | ||||
| extern mp_obj_t Encoder_counts_per_revolution(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); | ||||
| extern mp_obj_t Encoder_take_snapshot(mp_obj_t self_in); | ||||
|  | @ -5,7 +5,6 @@ add_library(usermod_${MOD_NAME} INTERFACE) | |||
| target_sources(usermod_${MOD_NAME} INTERFACE | ||||
|     ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.c | ||||
|     ${CMAKE_CURRENT_LIST_DIR}/${MOD_NAME}.cpp | ||||
|     ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/capture.cpp | ||||
|     ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.cpp | ||||
| ) | ||||
| pico_generate_pio_header(usermod_${MOD_NAME} ${CMAKE_CURRENT_LIST_DIR}/../../../drivers/encoder-pio/encoder.pio) | ||||
|  |  | |||
		Ładowanie…
	
		Reference in New Issue
	
	 ZodiusInfuser
						ZodiusInfuser