Skip to content

Commit

Permalink
RP.PIO.Touch_Sense: Add capacitive charge mode
Browse files Browse the repository at this point in the history
Anticipating the support of rp2350, this new mode is a workaround for
the rp2350 e9 eratum (pin pull-down lock).
  • Loading branch information
Fabien-Chouteau authored and JeremyGrosser committed Oct 14, 2024
1 parent 3ff0c10 commit 3321566
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 25 deletions.
33 changes: 25 additions & 8 deletions src/drivers/rp-pio-touch_sense.adb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
--
-- SPDX-License-Identifier: BSD-3-Clause
--
with RP.PIO.Touch_Sense_PIO;
with RP.PIO.Touch_Sense_Discharge_PIO; use RP.PIO.Touch_Sense_Discharge_PIO;
with RP.PIO.Touch_Sense_Charge_PIO; use RP.PIO.Touch_Sense_Charge_PIO;

package body RP.PIO.Touch_Sense is

Expand All @@ -12,24 +13,40 @@ package body RP.PIO.Touch_Sense is

procedure Initialize (This : in out Touch_Sensor;
ASM_Offset : PIO_Address := 0;
Max_Count : HAL.UInt32 := 10_000)
Max_Count : HAL.UInt32 := 10_000;
Mode : Touch_Mode := Discharge)
is
Config : PIO_SM_Config := Default_SM_Config;
begin
This.Max_Count := Max_Count;

This.PIO.Load
(Prog => Touch_Sense_PIO.Touch_Sense_Program_Instructions,
Offset => ASM_Offset);
case Mode is
when Discharge =>
This.PIO.Load
(Prog => Touch_Sense_Discharge_Program_Instructions,
Offset => ASM_Offset);
when Charge =>
This.PIO.Load
(Prog => Touch_Sense_Charge_Program_Instructions,
Offset => ASM_Offset);
end case;

This.Pin.Configure (Output, Floating, This.PIO.GPIO_Function);

Set_Jmp_Pin (Config, This.Pin.Pin);
Set_Set_Pins (Config, This.Pin.Pin, 1);

Set_Wrap (Config,
ASM_Offset + Touch_Sense_PIO.Touch_Sense_Wrap_Target,
ASM_Offset + Touch_Sense_PIO.Touch_Sense_Wrap);
case Mode is
when Discharge =>
Set_Wrap (Config,
ASM_Offset + Touch_Sense_Discharge_Wrap_Target,
ASM_Offset + Touch_Sense_Discharge_Wrap);

when Charge =>
Set_Wrap (Config,
ASM_Offset + Touch_Sense_Charge_Wrap_Target,
ASM_Offset + Touch_Sense_Charge_Wrap);
end case;

Set_Clock_Frequency (Config, 125_000_000);
This.PIO.SM_Initialize (This.SM, ASM_Offset, Config);
Expand Down
32 changes: 24 additions & 8 deletions src/drivers/rp-pio-touch_sense.ads
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,29 @@ is
-- introduced by the contact or proximity of the user finger(s) with a
-- pin.
--
-- Using PIO, any RP2040 pin connected to ground through a large resistor
-- (e.g. 1Mohm) can be a capacitive touch sensor.
-- Using PIO, any RP2040 pin connected to ground (or 3.3v) through a large
-- resistor (e.g. 1Mohm) can be a capacitive touch sensor.
--
-- The PIO program will charge the internal pin capacitor by configuring
-- the pin as an output and set it high for a few microseconds. And then
-- Two measure modes are available: Charge or Discharge
--
-- In Discharge mode (Default): Connect the pin to ground through a
-- large resistor. The PIO program will charge the internal pin capacitor
-- by configuring the pin as an output and set it high for a few
-- microseconds. And then set the pin as an input and count how many
-- cycles it takes for the capacitor to discharge through the resistor.
--
-- In Charge mode: Connect the pin to 3.3v through a large resistor. The
-- PIO program will discharge the internal pin capacitor by configuring
-- the pin as an output and set it low for a few microseconds. And then
-- set the pin as an input and count how many cycles it takes for the
-- capacitor to discharge through the resistor.
-- capacitor to charge through the resistor.
--
-- If users touch the pin, the capacitance will increase and therefore the
-- number of cycles it takes to discharge will increase as well.
-- number of cycles it takes to discharge/charge will increase as well.

type Touch_Mode is (Discharge, Charge);
-- Measure either capacitive discharge time (Pin pulled down) or
-- capacitive charge time (pin pulled up).

type Touch_Sensor
(Pin : not null access RP.GPIO.GPIO_Point;
Expand All @@ -41,12 +54,15 @@ is
-- Max_Count is the maximum number of loops in the PIO program for a
-- single measure. Lowering this number will shorten the measure time
-- in worst case (high capacitance).
--
-- Mode select either a discharge or charge count (see above).
procedure Initialize (This : in out Touch_Sensor;
ASM_Offset : PIO_Address := 0;
Max_Count : HAL.UInt32 := 10_000);
Max_Count : HAL.UInt32 := 10_000;
Mode : Touch_Mode := Discharge);

-- Trigger a measurement and return the number of cycles it took for the
-- capacitor to discharge.
-- capacitor to discharge/charge.
--
-- User touching the pin will increase capacitance, higher capacitance
-- means higher Raw_Value.
Expand Down
35 changes: 35 additions & 0 deletions src/drivers/rp-pio-touch_sense_charge_pio.ads
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--------------------------------------------------------
-- This file is autogenerated by pioasm; do not edit! --
--------------------------------------------------------

pragma Style_Checks (Off);

package RP.PIO.Touch_Sense_Charge_PIO
with Preelaborate
is

------------------------
-- Touch_Sense_Charge --
------------------------

Touch_Sense_Charge_Wrap_Target : constant := 0;
Touch_Sense_Charge_Wrap : constant := 12;

Touch_Sense_Charge_Program_Instructions : RP.PIO.Program := (
-- .wrap_target
16#80a0#, -- 0: pull block
16#e081#, -- 1: set pindirs, 1
16#e000#, -- 2: set pins, 0
16#e03e#, -- 3: set x, 30
16#1f44#, -- 4: jmp x--, 4 [31]
16#a027#, -- 5: mov x, osr
16#e080#, -- 6: set pindirs, 0
16#0049#, -- 7: jmp x--, 9
16#000b#, -- 8: jmp 11
16#00cb#, -- 9: jmp pin, 11
16#0007#, -- 10: jmp 7
16#a0c1#, -- 11: mov isr, x
16#8020#); -- 12: push block
-- .wrap

end RP.PIO.Touch_Sense_Charge_PIO;
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,18 @@

pragma Style_Checks (Off);

package RP.PIO.Touch_Sense_PIO
package RP.PIO.Touch_Sense_Discharge_PIO
with Preelaborate
is

-----------------
-- Touch_Sense --
-----------------
---------------------------
-- Touch_Sense_Discharge --
---------------------------

Touch_Sense_Wrap_Target : constant := 0;
Touch_Sense_Wrap : constant := 11;
Touch_Sense_Discharge_Wrap_Target : constant := 0;
Touch_Sense_Discharge_Wrap : constant := 11;

Touch_Sense_Program_Instructions : RP.PIO.Program := (
Touch_Sense_Discharge_Program_Instructions : RP.PIO.Program := (
-- .wrap_target
16#80a0#, -- 0: pull block
16#e081#, -- 1: set pindirs, 1
Expand All @@ -31,4 +31,4 @@ is
16#8020#); -- 11: push block
-- .wrap

end RP.PIO.Touch_Sense_PIO;
end RP.PIO.Touch_Sense_Discharge_PIO;
31 changes: 31 additions & 0 deletions src/drivers/touch_sense_charge.pio
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
; SPDX-FileCopyrightText: 2017 Scott Shawcroft, written for Adafruit Industries
; SPDX-FileCopyrightText: Copyright (c) 2023 Tod Kurt
;
; SPDX-License-Identifier: MIT


; See rp-pio-touch_sense.ads for more high level explanation of the touch
; sensing process.

.program touch_sense_charge

.wrap_target
pull block ; trigger a reading, get maxcount value from fifo, OSR contains maxcount
set pindirs, 1 ; set GPIO as output
set pins, 0 ; drive pin LOW to discharge capacitance
; set x,24 ; wait time for pin discharge
set x,30 ; wait time for pin discharge
discharge: ; wait (24+1)*31 = 1085 cycles = 8.6us
jmp x--, discharge [31]
mov x, osr ; load maxcount value (10_000 usually)
set pindirs, 0 ; set GPIO as input
timing:
jmp x--, test ; decrement x until timeout
jmp done ; we've timed out, so leave
test:
jmp pin, done ; exit when pin is becomes high
jmp timing ; loop otherwise
done:
mov isr, x ; load ISR with count value in x
push ; push ISR into RX fifo
.wrap
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
; See rp-pio-touch_sense.ads for more high level explanation of the touch
; sensing process.

.program touch_sense
.program touch_sense_discharge

.wrap_target
pull block ; trigger a reading, get maxcount value from fifo, OSR contains maxcount
Expand Down

0 comments on commit 3321566

Please sign in to comment.