-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RP.PIO.Touch_Sense: implement PIO based capacitive touch sensing
- Loading branch information
1 parent
dd57b8f
commit 70984e0
Showing
4 changed files
with
210 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
-- | ||
-- Copyright (C) 2022 Fabien Chouteau <[email protected]> | ||
-- | ||
-- SPDX-License-Identifier: BSD-3-Clause | ||
-- | ||
with RP.PIO.Touch_Sense_PIO; | ||
|
||
package body RP.PIO.Touch_Sense is | ||
|
||
function Initialized (This : Touch_Sensor) return Boolean | ||
is (This.Enabled); | ||
|
||
procedure Initialize (This : in out Touch_Sensor; | ||
ASM_Offset : PIO_Address := 0; | ||
Max_Count : HAL.UInt32 := 10_000) | ||
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); | ||
|
||
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); | ||
|
||
Set_Clock_Frequency (Config, 125_000_000); | ||
This.PIO.SM_Initialize (This.SM, ASM_Offset, Config); | ||
This.PIO.Set_Enabled (This.SM, True); | ||
|
||
This.Enabled := True; | ||
|
||
-- Do a first read to set a default threshold | ||
This.Threshold := This.Raw_Value + 200; | ||
end Initialize; | ||
|
||
function Raw_Value (This : Touch_Sensor) return HAL.UInt32 is | ||
Data : HAL.UInt32; | ||
begin | ||
if not This.Enabled then | ||
return 0; | ||
else | ||
This.PIO.Put (This.SM, This.Max_Count); | ||
This.PIO.Get (This.SM, Data); | ||
return This.Max_Count - Data; | ||
end if; | ||
end Raw_Value; | ||
|
||
function Touch (This : Touch_Sensor) return Boolean | ||
is (This.Raw_Value > This.Threshold); | ||
|
||
function Threshold (This : Touch_Sensor) return HAL.UInt32 | ||
is (This.Threshold); | ||
|
||
procedure Set_Threshold (This : in out Touch_Sensor; | ||
Threshold : HAL.UInt32) | ||
is | ||
begin | ||
This.Threshold := Threshold; | ||
end Set_Threshold; | ||
|
||
end RP.PIO.Touch_Sense; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
-- | ||
-- Copyright (C) 2024 Fabien Chouteau <[email protected]> | ||
-- | ||
-- SPDX-License-Identifier: BSD-3-Clause | ||
-- | ||
with RP.GPIO; | ||
|
||
package RP.PIO.Touch_Sense | ||
with Preelaborate | ||
is | ||
-- Capacitive touch sensing is based on change in capacitance typically | ||
-- 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. | ||
-- | ||
-- 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. | ||
-- | ||
-- If users touch the pin, the capacitance will increase and therefore the | ||
-- number of cycles it takes to discharge will increase as well. | ||
|
||
type Touch_Sensor | ||
(Pin : not null access RP.GPIO.GPIO_Point; | ||
PIO : not null access PIO_Device; | ||
SM : PIO_SM) | ||
is tagged private; | ||
|
||
-- Return True if the touch sensor is configured and ready to use | ||
function Initialized (This : Touch_Sensor) return Boolean; | ||
|
||
-- Configure the Pin, PIO and state machine for capacitive touch sensing. | ||
-- And set a default detection threshold based on a first measurement. | ||
-- | ||
-- ASM_Offset is the location in PIO memory where the PIO assembly code | ||
-- will be installed. | ||
-- | ||
-- 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). | ||
procedure Initialize (This : in out Touch_Sensor; | ||
ASM_Offset : PIO_Address := 0; | ||
Max_Count : HAL.UInt32 := 10_000); | ||
|
||
-- Trigger a measurement and return the number of cycles it took for the | ||
-- capacitor to discharge. | ||
-- | ||
-- User touching the pin will increase capacitance, higher capacitance | ||
-- means higher Raw_Value. | ||
function Raw_Value (This : Touch_Sensor) return HAL.UInt32; | ||
|
||
-- Return True if Raw_Value is above the detection threshold | ||
function Touch (This : Touch_Sensor) return Boolean; | ||
|
||
-- Return the threshold for touch detection | ||
function Threshold (This : Touch_Sensor) return HAL.UInt32; | ||
|
||
-- Set threshold for touch detection | ||
procedure Set_Threshold (This : in out Touch_Sensor; | ||
Threshold : HAL.UInt32); | ||
|
||
private | ||
|
||
type Touch_Sensor | ||
(Pin : not null access RP.GPIO.GPIO_Point; | ||
PIO : not null access PIO_Device; | ||
SM : PIO_SM) | ||
is tagged record | ||
Enabled : Boolean := False; | ||
Max_Count : HAL.UInt32; | ||
Threshold : HAL.UInt32 := HAL.UInt32'Last; | ||
end record; | ||
|
||
end RP.PIO.Touch_Sense; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
-------------------------------------------------------- | ||
-- This file is autogenerated by pioasm; do not edit! -- | ||
-------------------------------------------------------- | ||
|
||
pragma Style_Checks (Off); | ||
|
||
package RP.PIO.Touch_Sense_PIO | ||
with Preelaborate | ||
is | ||
|
||
----------------- | ||
-- Touch_Sense -- | ||
----------------- | ||
|
||
Touch_Sense_Wrap_Target : constant := 0; | ||
Touch_Sense_Wrap : constant := 11; | ||
|
||
Touch_Sense_Program_Instructions : RP.PIO.Program := ( | ||
-- .wrap_target | ||
16#80a0#, -- 0: pull block | ||
16#e081#, -- 1: set pindirs, 1 | ||
16#e001#, -- 2: set pins, 1 | ||
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#000a#, -- 8: jmp 10 | ||
16#00c7#, -- 9: jmp pin, 7 | ||
16#a0c1#, -- 10: mov isr, x | ||
16#8020#); -- 11: push block | ||
-- .wrap | ||
|
||
end RP.PIO.Touch_Sense_PIO; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
; 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 | ||
|
||
.wrap_target | ||
pull block ; trigger a reading, get maxcount value from fifo, OSR contains maxcount | ||
set pindirs, 1 ; set GPIO as output | ||
set pins, 1 ; drive pin HIGH to charge capacitance | ||
; set x,24 ; wait time for pin charge | ||
set x,30 ; wait time for pin charge | ||
charge: ; wait (24+1)*31 = 1085 cycles = 8.6us | ||
jmp x--, charge [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, timing ; loop while pin is still high | ||
done: | ||
mov isr, x ; load ISR with count value in x | ||
push ; push ISR into RX fifo | ||
.wrap |