added pio-based rotary encoder reading.
This commit is contained in:
		
							parent
							
								
									6f6ecc833e
								
							
						
					
					
						commit
						c726ab4aa7
					
				
					 3 changed files with 92 additions and 2 deletions
				
			
		| 
						 | 
					@ -20,6 +20,8 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
 | 
				
			||||||
rp-pico = "0.8"
 | 
					rp-pico = "0.8"
 | 
				
			||||||
max31855 = "0.1.0"
 | 
					max31855 = "0.1.0"
 | 
				
			||||||
hd44780-driver = "0.4.0"
 | 
					hd44780-driver = "0.4.0"
 | 
				
			||||||
 | 
					pio-proc = "0.2"
 | 
				
			||||||
 | 
					pio = "0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# cargo build/run
 | 
					# cargo build/run
 | 
				
			||||||
[profile.dev]
 | 
					[profile.dev]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										51
									
								
								src/encoder.pio
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/encoder.pio
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,51 @@
 | 
				
			||||||
 | 
					; from https://github.com/GitJer/Rotary_encoder/blob/master/pio_rotary_encoder.pio
 | 
				
			||||||
 | 
					.program pio_rotary_encoder
 | 
				
			||||||
 | 
					.wrap_target
 | 
				
			||||||
 | 
					.origin 0        ; The jump table has to start at 0
 | 
				
			||||||
 | 
					                 ; it contains the correct jumps for each of the 16
 | 
				
			||||||
 | 
					                 ; combination of 4 bits formed by A'B'AB
 | 
				
			||||||
 | 
					                 ; A = current reading of pin_A of the rotary encoder
 | 
				
			||||||
 | 
					                 ; A' = previous reading of pin_A of the rotary encoder
 | 
				
			||||||
 | 
					                 ; B = current reading of pin_B of the rotary encoder
 | 
				
			||||||
 | 
					                 ; B' = previous reading of pin_B of the rotary encoder
 | 
				
			||||||
 | 
					    jmp read     ; 0000 = from 00 to 00 = no change in reading
 | 
				
			||||||
 | 
					    jmp CW       ; 0001 = from 00 to 01 = clockwise rotation
 | 
				
			||||||
 | 
					    jmp CCW      ; 0010 = from 00 to 10 = counter clockwise rotation
 | 
				
			||||||
 | 
					    jmp read     ; 0011 = from 00 to 11 = error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jmp CCW      ; 0100 = from 01 to 00 = counter clockwise rotation
 | 
				
			||||||
 | 
					    jmp read     ; 0101 = from 01 to 01 = no change in reading
 | 
				
			||||||
 | 
					    jmp read     ; 0110 = from 01 to 10 = error
 | 
				
			||||||
 | 
					    jmp CW       ; 0111 = from 01 to 11 = clockwise rotation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jmp CW       ; 1000 = from 10 to 00 = clockwise rotation
 | 
				
			||||||
 | 
					    jmp read     ; 1001 = from 10 to 01 = error
 | 
				
			||||||
 | 
					    jmp read     ; 1010 = from 10 to 10 = no change in reading
 | 
				
			||||||
 | 
					    jmp CCW      ; 1011 = from 10 to 11 = counter clockwise rotation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    jmp read     ; 1100 = from 11 to 00 = error
 | 
				
			||||||
 | 
					    jmp CCW      ; 1101 = from 11 to 01 = counter clockwise rotation
 | 
				
			||||||
 | 
					    jmp CW       ; 1110 = from 11 to 10 = clockwise rotation
 | 
				
			||||||
 | 
					    jmp read     ; 1111 = from 11 to 11 = no change in reading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pc_start:        ; this is the entry point for the program
 | 
				
			||||||
 | 
					    in pins 2    ; read the current values of A and B and use
 | 
				
			||||||
 | 
					                 ; them to initialize the previous values (A'B')
 | 
				
			||||||
 | 
					read:
 | 
				
			||||||
 | 
					    mov osr isr  ; the OSR is (after the next instruction) used to shift
 | 
				
			||||||
 | 
					                 ; the two bits with the previous values into the ISR
 | 
				
			||||||
 | 
					    out isr 2    ; shift the previous value into the ISR. This also sets
 | 
				
			||||||
 | 
					                 ; all other bits in the ISR to 0
 | 
				
			||||||
 | 
					    in pins 2    ; shift the current value into the ISR
 | 
				
			||||||
 | 
					                 ; the 16 LSB of the ISR now contain 000000000000A'B'AB
 | 
				
			||||||
 | 
					                 ; this represents a jmp instruction to the address A'B'AB
 | 
				
			||||||
 | 
					    mov exec isr ; do the jmp encoded in the ISR
 | 
				
			||||||
 | 
					CW:              ; a clockwise rotation was detected
 | 
				
			||||||
 | 
					    irq 0        ; signal a clockwise rotation via an IRQ
 | 
				
			||||||
 | 
					    jmp read     ; jump to reading the current values of A and B
 | 
				
			||||||
 | 
					CCW:             ; a counter clockwise rotation was detected
 | 
				
			||||||
 | 
					    irq 1        ; signal a counter clockwise rotation via an IRQ
 | 
				
			||||||
 | 
					;    jmp read    ; jump to reading the current values of A and B.
 | 
				
			||||||
 | 
					                 ; the jmp isn't needed because of the .wrap, and the first
 | 
				
			||||||
 | 
					                 ; statement of the program happens to be a jmp read
 | 
				
			||||||
 | 
					.wrap
 | 
				
			||||||
							
								
								
									
										41
									
								
								src/main.rs
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								src/main.rs
									
										
									
									
									
								
							| 
						 | 
					@ -28,14 +28,15 @@ mod app {
 | 
				
			||||||
                    Gpio0, Gpio1, Gpio14, Gpio16, Gpio17, Gpio18, Gpio19, Gpio2, Gpio20, Gpio21,
 | 
					                    Gpio0, Gpio1, Gpio14, Gpio16, Gpio17, Gpio18, Gpio19, Gpio2, Gpio20, Gpio21,
 | 
				
			||||||
                    Gpio25, Gpio3, Gpio4, Gpio5,
 | 
					                    Gpio25, Gpio3, Gpio4, Gpio5,
 | 
				
			||||||
                },
 | 
					                },
 | 
				
			||||||
                FunctionSio, FunctionSpi, FunctionUart, Pin, PullDown, SioOutput,
 | 
					                FunctionPio0, FunctionSio, FunctionSpi, FunctionUart, Pin, PullDown, SioOutput,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
 | 
					            pio::PIOExt,
 | 
				
			||||||
            sio::Sio,
 | 
					            sio::Sio,
 | 
				
			||||||
            spi::{self, Spi},
 | 
					            spi::{self, Spi},
 | 
				
			||||||
            uart::{self, UartConfig, UartPeripheral},
 | 
					            uart::{self, UartConfig, UartPeripheral},
 | 
				
			||||||
            watchdog::Watchdog,
 | 
					            watchdog::Watchdog,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
        pac::{SPI0, UART0},
 | 
					        pac::{self, SPI0, UART0},
 | 
				
			||||||
        Pins,
 | 
					        Pins,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,6 +120,7 @@ mod app {
 | 
				
			||||||
    #[init]
 | 
					    #[init]
 | 
				
			||||||
    fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) {
 | 
					    fn init(mut ctx: init::Context) -> (Shared, Local, init::Monotonics) {
 | 
				
			||||||
        let mut watchdog = Watchdog::new(ctx.device.WATCHDOG);
 | 
					        let mut watchdog = Watchdog::new(ctx.device.WATCHDOG);
 | 
				
			||||||
 | 
					        let mut pac = pac::Peripherals::take().unwrap();
 | 
				
			||||||
        let sio = Sio::new(ctx.device.SIO);
 | 
					        let sio = Sio::new(ctx.device.SIO);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // External high-speed crystal on the pico board is 12Mhz
 | 
					        // External high-speed crystal on the pico board is 12Mhz
 | 
				
			||||||
| 
						 | 
					@ -212,6 +214,25 @@ mod app {
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .unwrap();
 | 
					        .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let rotary_clk: Pin<_, FunctionPio0, _> = pins.gpio11.into_function();
 | 
				
			||||||
 | 
					        let rotary_clk_id = rotary_clk.id().num;
 | 
				
			||||||
 | 
					        let rotary_dt: Pin<_, FunctionPio0, _> = pins.gpio12.into_function();
 | 
				
			||||||
 | 
					        let rotary_dt_id = rotary_dt.id().num;
 | 
				
			||||||
 | 
					        let program = pio_proc::pio_file!("src/encoder.pio");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let (mut pio, sm0, _, _, _) = pac.PIO0.split(&mut pac.RESETS);
 | 
				
			||||||
 | 
					        pio.irq0().enable_sm_interrupt(0);
 | 
				
			||||||
 | 
					        pio.irq1().enable_sm_interrupt(1);
 | 
				
			||||||
 | 
					        let installed = pio.install(&program.program).unwrap();
 | 
				
			||||||
 | 
					        let (mut sm, _, _) = rp_pico::hal::pio::PIOBuilder::from_program(installed)
 | 
				
			||||||
 | 
					            .set_pins(rotary_clk_id, 2)
 | 
				
			||||||
 | 
					            .build(sm0);
 | 
				
			||||||
 | 
					        sm.set_pindirs([
 | 
				
			||||||
 | 
					            (rotary_clk_id, rp_pico::hal::pio::PinDir::Output),
 | 
				
			||||||
 | 
					            (rotary_dt_id, rp_pico::hal::pio::PinDir::Output),
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					        sm.start();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let mono = Rp2040Mono::new(ctx.device.TIMER);
 | 
					        let mono = Rp2040Mono::new(ctx.device.TIMER);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        heartbeat::spawn().unwrap();
 | 
					        heartbeat::spawn().unwrap();
 | 
				
			||||||
| 
						 | 
					@ -234,6 +255,22 @@ mod app {
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[task(binds = PIO0_IRQ_0, shared = [target_temp])]
 | 
				
			||||||
 | 
					    fn inc_target(mut ctx: inc_target::Context) {
 | 
				
			||||||
 | 
					        ctx.shared.target_temp.lock(|t| {
 | 
				
			||||||
 | 
					            *t += 1.0;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        update_display::spawn().unwrap();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #[task(binds = PIO0_IRQ_1, shared = [target_temp])]
 | 
				
			||||||
 | 
					    fn dec_target(mut ctx: dec_target::Context) {
 | 
				
			||||||
 | 
					        ctx.shared.target_temp.lock(|t| {
 | 
				
			||||||
 | 
					            *t -= 1.0;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        update_display::spawn().unwrap();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #[task(local = [thermocouple], shared = [recent_temp, uart])]
 | 
					    #[task(local = [thermocouple], shared = [recent_temp, uart])]
 | 
				
			||||||
    fn read_temp(mut ctx: read_temp::Context) {
 | 
					    fn read_temp(mut ctx: read_temp::Context) {
 | 
				
			||||||
        match ctx.local.thermocouple.read_temp() {
 | 
					        match ctx.local.thermocouple.read_temp() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue