Skip to content

Commit 8f6dcfa

Browse files
committed
improved touch2046
1 parent de16c0f commit 8f6dcfa

File tree

3 files changed

+169
-83
lines changed

3 files changed

+169
-83
lines changed

src/modm/driver/touch/touch2046.hpp

Lines changed: 91 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// coding: utf-8
22
/*
33
* Copyright (c) 2021, Raphael Lehmann
4+
* Copyright (c) 2021, Thomas Sommer
45
*
56
* This file is part of the modm project.
67
*
@@ -19,16 +20,70 @@
1920

2021
#include <array>
2122
#include <tuple>
23+
#include <modm/ui/graphic/display.hpp>
24+
#include <modm/ui/shape/point.hpp>
2225

2326
namespace modm
2427
{
2528

2629
/// \ingroup modm_driver_touch2046
2730
struct touch2046 {
28-
enum class Orientation {
29-
Normal,
30-
//...
31+
enum class Control : uint8_t
32+
{
33+
START = Bit7, // 1: Marks the control byte
34+
35+
A2 = Bit6, // see enum class ChDiff / ChSingleEnd
36+
A1 = Bit5,
37+
A0 = Bit4,
38+
39+
MODE = Bit3, // see enum class Mode
40+
REF = Bit2, // see enum class Reference
41+
42+
PD1 = Bit1, // see enum class PowerDown
43+
PD0 = Bit0,
44+
};
45+
MODM_FLAGS8(Control);
46+
47+
// Valid when Control::MODE is 0
48+
enum class ChDiff : uint8_t
49+
{
50+
Z1 = int(Control::A0) | int(Control::A1),
51+
Z2 = int(Control::A2),
52+
X = int(Control::A0) | int(Control::A2),
53+
Y = int(Control::A0)
54+
};
55+
typedef Configuration<Control_t, ChDiff, 0b111'0000> ChDiff_t;
56+
57+
// Valid when Control::MODE is 1
58+
enum class ChSingleEnd : uint8_t
59+
{
60+
// TODO see Datasheet P10 Table 1
61+
};
62+
typedef Configuration<Control_t, ChSingleEnd, 0b111'0000> ChSingleEnd_t;
63+
64+
enum class Mode : uint8_t
65+
{
66+
Res_12Bit = 0,
67+
Res_8Bit = int(Control::MODE)
68+
};
69+
typedef Configuration<Control_t, Mode, 0b1, 3> Mode_t;
70+
71+
enum class Reference : uint8_t
72+
{
73+
Differential = 0,
74+
SingleEnded = int(Control::REF)
75+
};
76+
typedef Configuration<Control_t, Reference, 0b1, 2> Reference_t;
77+
78+
enum class PowerDown : uint8_t
79+
{
80+
Auto = 0,
81+
RefOff_AdcOn = int(Control::PD0),
82+
RefOn_AdcOff = int(Control::PD1),
83+
AlwaysOn = int(Control::PD0) | int(Control::PD1)
3184
};
85+
typedef Configuration<Control_t, PowerDown, 0b11, 0> PowerDown_t;
86+
3287

3388
/**
3489
* Calibration values are used to calculate touch point
@@ -44,33 +99,30 @@ struct touch2046 {
4499
* limited to [0, MaxX]
45100
* Y = (rawY * FactorY / 1000000) + OffsetY
46101
* limited to [0, MaxY]
47-
*
48-
* Orientation (rotation, mirror) are applied after the
49-
* above operations.
50102
*/
103+
51104
struct Calibration
52105
{
53106
int16_t OffsetX = 0;
54107
int16_t OffsetY = 0;
55108
int32_t FactorX = 1'000'000;
56109
int32_t FactorY = 1'000'000;
57-
uint16_t MaxX = 240;
58-
uint16_t MaxY = 320;
59110
uint16_t ThresholdZ = 1500;
60-
Orientation orientation = Orientation::Normal;
61111
};
62112
};
63113

64114
/**
65115
* \ingroup modm_driver_touch2046
66-
* \author Raphael Lehmann
116+
* \author Raphael Lehmann, Thomas Sommer
67117
*
68118
* Datasheet TSC2046: https://www.ti.com/lit/ds/symlink/tsc2046.pdf
69119
*/
70-
template < class SpiMaster, class Cs>
120+
template < class SpiMaster, class Cs, Resolution R>
71121
class Touch2046 : public touch2046, public modm::SpiDevice< SpiMaster >, protected modm::NestedResumable<3>
72122
{
73123
public:
124+
using Orientation = modm::graphic::Orientation;
125+
74126
/**
75127
* Set calibration data
76128
*
@@ -81,14 +133,6 @@ class Touch2046 : public touch2046, public modm::SpiDevice< SpiMaster >, protect
81133
cal = calibration;
82134
}
83135

84-
/**
85-
* Get raw X, Y and Z values
86-
*
87-
* \return Position and intensity of touch point. Full int16_t range.
88-
*/
89-
modm::ResumableResult<std::tuple<uint16_t,uint16_t,uint16_t>>
90-
getRawValues();
91-
92136
/**
93137
* Is screen touched?
94138
*
@@ -98,36 +142,47 @@ class Touch2046 : public touch2046, public modm::SpiDevice< SpiMaster >, protect
98142
isTouched();
99143

100144
/**
101-
* Get touch position
145+
* Get touch position as tuple
102146
*
103147
* \return Position (X, Y) of touch point.
104148
*/
105149
modm::ResumableResult<std::tuple<uint16_t,uint16_t>>
106150
getTouchPosition();
107151

152+
/**
153+
* Get touch position as modm::shape::Point
154+
*
155+
* \return Point of touch point.
156+
*/
157+
modm::ResumableResult<modm::shape::Point>
158+
getTouchPoint();
159+
160+
void setOrientation(Orientation orientation)
161+
{ this->orientation = orientation; }
162+
163+
Orientation getOrientation() const
164+
{ return orientation; }
165+
108166
private:
109-
static constexpr uint8_t MeasureZ1 = 0xB1;
110-
static constexpr uint8_t MeasureZ2 = 0xC1;
111-
static constexpr uint8_t MeasureX = 0xD1;
112-
static constexpr uint8_t MeasureY = 0x91;
113-
static constexpr uint8_t Powerdown = 0b1111'1100;
114-
static constexpr std::array<uint8_t, 17> bufferWrite = {
115-
MeasureZ1, 0x00,
116-
MeasureZ2, 0x00,
117-
MeasureY, 0x00,
118-
MeasureX, 0x00,
119-
MeasureY, 0x00,
120-
MeasureX, 0x00,
121-
MeasureY, 0x00,
122-
(MeasureX & Powerdown), 0x00,
123-
0x00};
124-
std::array<uint16_t, 9> bufferRead = {};
167+
modm::ResumableResult<void>
168+
updateZ();
169+
170+
modm::ResumableResult<void>
171+
updateXY();
172+
173+
static constexpr Control_t Measure = Control::START | Mode_t(Mode::Res_12Bit)
174+
| Reference_t(Reference::Differential) | PowerDown_t(PowerDown::RefOff_AdcOn);
175+
176+
std::array<uint16_t, 6> bufferWrite = {};
177+
std::array<uint16_t, 6> bufferRead = {};
125178

126179
uint16_t x = 0;
127180
uint16_t y = 0;
128181
uint16_t z = 0;
129182

130183
Calibration cal;
184+
185+
Orientation orientation = Orientation::Portrait90;
131186
};
132187

133188
} // modm namespace
Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// coding: utf-8
22
/*
33
* Copyright (c) 2021, Raphael Lehmann
4+
* Copyright (c) 2021, Thomas Sommer
45
*
56
* This file is part of the modm project.
67
*
@@ -10,70 +11,99 @@
1011
*/
1112
// ----------------------------------------------------------------------------
1213

13-
#ifndef MODM_TOUCH2046_HPP
14-
#error "Don't include this file directly, use 'touch2046.hpp' instead!"
15-
#endif
14+
#pragma once
15+
#include "touch2046.hpp"
1616

17+
#include <modm/math/utils/endianness.hpp>
1718

18-
template < class SpiMaster, class Cs >
19-
modm::ResumableResult<std::tuple<uint16_t,uint16_t,uint16_t>>
20-
modm::Touch2046<SpiMaster, Cs>::getRawValues()
19+
template<class SpiMaster, class Cs, Resolution R>
20+
modm::ResumableResult<void>
21+
modm::Touch2046<SpiMaster, Cs, R>::updateZ()
2122
{
2223
RF_BEGIN();
2324

25+
bufferWrite[0] = (Measure | ChDiff_t(ChDiff::Z1)).value;
26+
bufferWrite[1] = (Measure | ChDiff_t(ChDiff::Z2)).value;
27+
bufferWrite[2] = 0; // not required but cleaner on ossziloscope
28+
2429
RF_WAIT_UNTIL(this->acquireMaster());
2530
Cs::reset();
2631

27-
RF_CALL(SpiMaster::transfer(
28-
bufferWrite.data(),
29-
reinterpret_cast<uint8_t*>(bufferRead.data()) + 1,
30-
17));
32+
RF_CALL(SpiMaster::template transfer<16>(bufferWrite.data(), bufferRead.data(), 3));
33+
34+
z = 4095 + (bufferRead[1] >> 3) - (bufferRead[2] >> 3);
35+
36+
if (this->releaseMaster())
37+
Cs::set();
3138

32-
z = 4095 + (modm::fromBigEndian(bufferRead[1]) >> 3)
33-
- (modm::fromBigEndian(bufferRead[2]) >> 3);
39+
RF_END_RETURN();
40+
}
3441

35-
y = (modm::fromBigEndian(bufferRead[3]) >> 3)
36-
+ (modm::fromBigEndian(bufferRead[5]) >> 3)
37-
+ (modm::fromBigEndian(bufferRead[7]) >> 3);
42+
template<class SpiMaster, class Cs, Resolution R>
43+
modm::ResumableResult<void>
44+
modm::Touch2046<SpiMaster, Cs, R>::updateXY()
45+
{
46+
RF_BEGIN();
47+
48+
bufferWrite[0] = (Measure | ChDiff_t(ChDiff::X)).value;
49+
bufferWrite[1] = (Measure | ChDiff_t(ChDiff::Y)).value;
50+
bufferWrite[2] = (Measure | ChDiff_t(ChDiff::X)).value;
51+
bufferWrite[3] = (Measure | ChDiff_t(ChDiff::Y)).value;
52+
bufferWrite[4] = (Measure | ChDiff_t(ChDiff::X)).value;
53+
bufferWrite[5] = ((Measure | ChDiff_t(ChDiff::Y)) & ~PowerDown_t::mask()).value;
54+
55+
RF_WAIT_UNTIL(this->acquireMaster());
56+
Cs::reset();
3857

39-
x = (modm::fromBigEndian(bufferRead[4]) >> 3)
40-
+ (modm::fromBigEndian(bufferRead[6]) >> 3)
41-
+ (modm::fromBigEndian(bufferRead[8]) >> 3);
58+
RF_CALL(SpiMaster::template transfer<16>(bufferWrite.data(), bufferRead.data(), 6));
4259

43-
if (this->releaseMaster()) {
60+
if (this->releaseMaster())
4461
Cs::set();
45-
}
4662

47-
RF_END_RETURN(std::make_tuple(x, y, z));
63+
x = (bufferRead[1] >> 3) + (bufferRead[3] >> 3) + (bufferRead[5] >> 3);
64+
y = (bufferRead[2] >> 3) + (bufferRead[4] >> 3) + (bufferRead[6] >> 3);
65+
66+
x = std::min<uint16_t>((((uint32_t)(x * cal.FactorX) / 1'000'000) + cal.OffsetX), R.x);
67+
y = std::min<uint16_t>((((uint32_t)(y * cal.FactorY) / 1'000'000) + cal.OffsetY), R.y);
68+
69+
RF_END_RETURN();
4870
}
4971

50-
template < class SpiMaster, class Cs >
72+
template<class SpiMaster, class Cs, Resolution R>
5173
modm::ResumableResult<bool>
52-
modm::Touch2046<SpiMaster, Cs>::isTouched()
74+
modm::Touch2046<SpiMaster, Cs, R>::isTouched()
5375
{
5476
RF_BEGIN();
55-
std::tie(std::ignore, std::ignore, z) = RF_CALL(getRawValues());
77+
RF_CALL(updateZ());
5678
RF_END_RETURN(z > cal.ThresholdZ);
5779
}
5880

59-
template < class SpiMaster, class Cs >
60-
modm::ResumableResult<std::tuple<uint16_t,uint16_t>>
61-
modm::Touch2046<SpiMaster, Cs>::getTouchPosition()
81+
template<class SpiMaster, class Cs, Resolution R>
82+
modm::ResumableResult<modm::shape::Point>
83+
modm::Touch2046<SpiMaster, Cs, R>::getTouchPoint()
6284
{
6385
RF_BEGIN();
86+
RF_CALL(updateXY());
87+
// TODO evaluate orientation & modm::graphic::OrientationFlags::TopDown
88+
if (orientation & modm::graphic::OrientationFlags::Portrait) {
89+
RF_RETURN(modm::shape::Point(x, y));
90+
} else {
91+
RF_RETURN(modm::shape::Point(y, x));
92+
}
93+
RF_END();
94+
}
6495

65-
std::tie(x, y, std::ignore) = RF_CALL(getRawValues());
66-
67-
x = std::min<uint16_t>(
68-
((static_cast<int32_t>(x * cal.FactorX) / 1'000'000)
69-
+ cal.OffsetX),
70-
cal.MaxX);
71-
y = std::min<uint16_t>(
72-
((static_cast<int32_t>(y * cal.FactorY) / 1'000'000)
73-
+ cal.OffsetY),
74-
cal.MaxY);
75-
76-
// todo: orientation processing
77-
78-
RF_END_RETURN(std::make_tuple(x, y));
96+
template<class SpiMaster, class Cs, Resolution R>
97+
modm::ResumableResult<std::tuple<uint16_t, uint16_t>>
98+
modm::Touch2046<SpiMaster, Cs, R>::getTouchPosition()
99+
{
100+
RF_BEGIN();
101+
RF_CALL(updateXY());
102+
// TODO evaluate orientation & modm::graphic::OrientationFlags::TopDown
103+
if (orientation & modm::graphic::OrientationFlags::Portrait) {
104+
RF_RETURN(std::make_tuple(x, y));
105+
} else {
106+
RF_RETURN(std::make_tuple(y, x));
107+
}
108+
RF_END();
79109
}

src/modm/ui/graphic/display.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ class Display : virtual public Canvas<R>
5555
public:
5656
C color;
5757

58+
Orientation getOrientation() const
59+
{ return orientation; }
60+
5861
int16_t
5962
getWidth() const override
6063
{ return (orientation & OrientationFlags::Portrait) ? R.y : R.x; }
@@ -67,15 +70,12 @@ class Display : virtual public Canvas<R>
6770
getSize() const override
6871
{ return (orientation & OrientationFlags::Portrait) ? R.swapped() : R; }
6972

70-
Orientation getOrientation() const
71-
{ return orientation; }
72-
7373
protected:
7474
Display(C color) : color(color) {};
7575

7676
Orientation orientation = Orientation::Landscape0;
7777

78-
// Static variables for Resumable Functions required for any Display-type
78+
// Static variables for Resumable Functions
7979
shape::Section clipping;
8080
};
8181

@@ -86,14 +86,15 @@ class Display<C, R, false> : virtual public Canvas<R>
8686
public:
8787
C color;
8888

89-
Orientation
90-
getOrientation() const { return orientation; }
89+
Orientation getOrientation() const
90+
{ return orientation; }
9191

9292
protected:
9393
Display(C color) : color(color) {};
9494

9595
Orientation orientation = Orientation::Landscape0;
9696

97+
// Static variables for Resumable Functions
9798
shape::Section clipping;
9899
};
99100

0 commit comments

Comments
 (0)