Skip to content

Commit a10c9dc

Browse files
committed
Merge branch 'bit-resolution-Spi' into rewrite-graphics-API
2 parents c0f0fd0 + 321b0af commit a10c9dc

17 files changed

+255
-152
lines changed

src/modm/driver/display/ili9341_interface_spi.hpp

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,23 @@ template<class SpiMaster, class Cs, class Dc>
2626
class Ili9341InterfaceSpi : public ili9341_register, public modm::SpiDevice< SpiMaster >, protected modm::NestedResumable<5>
2727
{
2828
uint8_t read;
29+
30+
static constexpr auto configuration8bit = []() {
31+
SpiMaster::setDataMode(SpiMaster::DataMode::Mode0);
32+
SpiMaster::setDataOrder(SpiMaster::DataOrder::MsbFirst);
33+
SpiMaster::setDataSize(SpiMaster::DataSize::Bit8);
34+
};
35+
36+
static constexpr auto configuration16bit = []() {
37+
SpiMaster::setDataMode(SpiMaster::DataMode::Mode0);
38+
SpiMaster::setDataOrder(SpiMaster::DataOrder::MsbFirst);
39+
SpiMaster::setDataSize(SpiMaster::DataSize::Bit16);
40+
};
41+
2942
protected:
3043
Ili9341InterfaceSpi()
3144
{
32-
this->attachConfigurationHandler([]() {
33-
SpiMaster::setDataMode(SpiMaster::DataMode::Mode0);
34-
SpiMaster::setDataOrder(SpiMaster::DataOrder::MsbFirst);
35-
SpiMaster::setDataSize(SpiMaster::DataSize::Bit16);
36-
});
45+
this->attachConfigurationHandler(configuration16bit);
3746
Cs::setOutput(modm::Gpio::High);
3847
Dc::setOutput();
3948
}
@@ -47,7 +56,7 @@ class Ili9341InterfaceSpi : public ili9341_register, public modm::SpiDevice< Spi
4756
Cs::reset();
4857

4958
Dc::reset();
50-
RF_CALL(SpiMaster::transfer(uint8_t(command)));
59+
RF_CALL(SpiMaster::transfer(uint16_t(command))); // It's Ok to send sole commands in 16bit
5160
Dc::set();
5261

5362
if (this->releaseMaster())
@@ -60,6 +69,7 @@ class Ili9341InterfaceSpi : public ili9341_register, public modm::SpiDevice< Spi
6069
writeCommand(Command command, const uint8_t data)
6170
{
6271
RF_BEGIN();
72+
this->attachConfigurationHandler(configuration8bit);
6373

6474
RF_WAIT_UNTIL(this->acquireMaster());
6575
Cs::reset();
@@ -73,23 +83,45 @@ class Ili9341InterfaceSpi : public ili9341_register, public modm::SpiDevice< Spi
7383
if (this->releaseMaster())
7484
Cs::set();
7585

86+
this->attachConfigurationHandler(configuration16bit);
87+
RF_END();
88+
}
89+
90+
modm::ResumableResult<void>
91+
writeCommand(Command command, const uint8_t *data, uint16_t length)
92+
{
93+
RF_BEGIN();
94+
this->attachConfigurationHandler(configuration8bit);
95+
96+
RF_WAIT_UNTIL(this->acquireMaster());
97+
Cs::reset();
98+
99+
Dc::reset();
100+
RF_CALL(SpiMaster::transfer(uint8_t(command)));
101+
Dc::set();
102+
103+
RF_CALL(SpiMaster::transfer(data, (uint8_t*)(nullptr), length));
104+
105+
if (this->releaseMaster())
106+
Cs::set();
107+
108+
this->attachConfigurationHandler(configuration16bit);
76109
RF_END();
77110
}
78111

79-
template<std::unsigned_integral T>
80112
modm::ResumableResult<void>
81-
writeCommand(Command command, const T *data, uint16_t length)
113+
writeCommand(Command command, const uint16_t *data, uint16_t length)
82114
{
83115
RF_BEGIN();
84116

85117
RF_WAIT_UNTIL(this->acquireMaster());
86118
Cs::reset();
87119

88120
Dc::reset();
89-
RF_CALL(SpiMaster::transfer(uint16_t(command)));
121+
RF_CALL(SpiMaster::transfer(uint16_t(command))); // It's Ok to send sole commands in 16bit
90122
Dc::set();
91123

92-
RF_CALL(SpiMaster::template transfer<T>(data, nullptr, length));
124+
RF_CALL(SpiMaster::transfer(data, (uint16_t*)(nullptr), length));
93125

94126
if (this->releaseMaster())
95127
Cs::set();
@@ -121,7 +153,7 @@ class Ili9341InterfaceSpi : public ili9341_register, public modm::SpiDevice< Spi
121153
RF_WAIT_UNTIL(this->acquireMaster());
122154
Cs::reset();
123155

124-
RF_CALL(SpiMaster::template transfer<Rgb565::ValueType>((Rgb565::ValueType*)(pixel), repeat));
156+
RF_CALL(SpiMaster::template transfer<uint16_t>((uint16_t*)(pixel), repeat));
125157

126158
if (this->releaseMaster())
127159
Cs::set();
@@ -137,7 +169,7 @@ class Ili9341InterfaceSpi : public ili9341_register, public modm::SpiDevice< Spi
137169
RF_WAIT_UNTIL(this->acquireMaster());
138170
Cs::reset();
139171

140-
RF_CALL(SpiMaster::template transfer<Rgb565::ValueType>((Rgb565::ValueType*)(pixels), nullptr, length));
172+
RF_CALL(SpiMaster::template transfer<uint16_t>((uint16_t*)(pixels), nullptr, length));
141173

142174
if (this->releaseMaster())
143175
Cs::set();

src/modm/driver/touch/touch2046.hpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ struct touch2046 {
3535
A2 = Bit6, // see enum class ChDiff / ChSingleEnd
3636
A1 = Bit5,
3737
A0 = Bit4,
38-
3938
MODE = Bit3, // see enum class Mode
4039
REF = Bit2, // see enum class Reference
4140

@@ -124,15 +123,7 @@ template < class SpiMaster, class Cs, Size R>
124123
class Touch2046 : public touch2046, public modm::SpiDevice< SpiMaster >, protected modm::NestedResumable<3>
125124
{
126125
public:
127-
Touch2046() {
128-
this->attachConfigurationHandler([]() {
129-
SpiMaster::setDataMode(SpiMaster::DataMode::Mode0);
130-
SpiMaster::setDataOrder(SpiMaster::DataOrder::MsbFirst);
131-
SpiMaster::setDataSize(SpiMaster::DataSize::Bit16);
132-
});
133-
134-
Cs::setOutput(true);
135-
}
126+
Touch2046();
136127

137128
using Orientation = modm::graphic::Orientation;
138129

@@ -185,7 +176,6 @@ class Touch2046 : public touch2046, public modm::SpiDevice< SpiMaster >, protect
185176

186177
static constexpr Control_t Measure = Control::START | Mode_t(Mode::Res_12Bit)
187178
| Reference_t(Reference::Differential) | PowerDown_t(PowerDown::RefOff_AdcOn);
188-
189179
static constexpr std::array<uint16_t, 8> bufferWrite = {
190180
(Measure | ChDiff_t(ChDiff::Z1)).value,
191181
((Measure | ChDiff_t(ChDiff::Z2)) & ~PowerDown_t::mask()).value,

src/modm/driver/touch/touch2046_impl.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616

1717
#include <modm/math/utils/endianness.hpp>
1818

19+
template<class SpiMaster, class Cs, Size R>
20+
modm::Touch2046<SpiMaster, Cs, R>::Touch2046()
21+
{
22+
this->attachConfigurationHandler([]() {
23+
SpiMaster::setDataMode(SpiMaster::DataMode::Mode0);
24+
SpiMaster::setDataOrder(SpiMaster::DataOrder::MsbFirst);
25+
SpiMaster::setDataSize(SpiMaster::DataSize::Bit16);
26+
});
27+
28+
Cs::setOutput(true);
29+
}
30+
1931
template<class SpiMaster, class Cs, Size R>
2032
modm::ResumableResult<void>
2133
modm::Touch2046<SpiMaster, Cs, R>::updateZ()

src/modm/platform/dma/stm32/dma_hal.hpp.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ public:
256256

257257
/**
258258
* Set length of data to transfer
259-
*
259+
*
260260
* @param lenght range: 0-65535
261261
*/
262262
static void

src/modm/platform/spi/at90_tiny_mega/module.lb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class Instance(Module):
5050

5151
env.template("spi.hpp.in", "spi{}.hpp".format(self.instance))
5252
env.template("spi_master.hpp.in", "spi_master{}.hpp".format(self.instance))
53+
env.template("spi_master_impl.hpp.in", "spi_master{}_impl.hpp".format(self.instance))
5354
env.template("spi_master.cpp.in", "spi_master{}.cpp".format(self.instance))
5455

5556
def init(module):

src/modm/platform/spi/at90_tiny_mega/spi_master.cpp.in

Lines changed: 68 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@
1919
#include <modm/math/utils/bit_constants.hpp>
2020
#include <modm/architecture/interface/atomic_lock.hpp>
2121

22-
// bit 7 (0x80) is used for transfer 1 byte
23-
// bit 6 (0x40) is used for transfer multiple byte
24-
// bit 5-0 (0x3f) are used to store the acquire count
22+
// bit 7 (0x80) is used for transfer 2nd byte
23+
// bit 6 (0x40) is used for transfer 1th byte
24+
// bit 5 (0x20) is used for transfer multiple T
25+
// bit 4-0 (0x1f) are used to store the acquire count
2526
uint8_t
2627
modm::platform::SpiMaster{{ id }}::state(0);
2728

29+
uint8_t
30+
modm::platform::SpiMaster::read(0);
31+
2832
void *
2933
modm::platform::SpiMaster{{ id }}::context(nullptr);
3034

@@ -39,7 +43,7 @@ modm::platform::SpiMaster{{ id }}::initialize(Prescaler prescaler)
3943

4044
SPCR{{ id }} = (1 << SPE{{ id }}) | (1 << MSTR{{ id }}) | (static_cast<uint8_t>(prescaler) & ~0x80);
4145
SPSR{{ id }} = (static_cast<uint8_t>(prescaler) & 0x80) ? (1 << SPI2X{{ id }}) : 0;
42-
state &= 0x3f;
46+
state &= 0x1f;
4347
}
4448
// ----------------------------------------------------------------------------
4549

@@ -49,7 +53,7 @@ modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handl
4953
if (context == nullptr)
5054
{
5155
context = ctx;
52-
state = (state & ~0x3f) | 1;
56+
state = (state & ~0x1f) | 1;
5357
// if handler is not nullptr and is different from previous configuration
5458
if (handler and configuration != handler) {
5559
configuration = handler;
@@ -59,7 +63,7 @@ modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handl
5963
}
6064

6165
if (ctx == context)
62-
return (++state & 0x3f);
66+
return (++state & 0x1f);
6367

6468
return 0;
6569
}
@@ -69,15 +73,15 @@ modm::platform::SpiMaster{{ id }}::release(void *ctx)
6973
{
7074
if (ctx == context)
7175
{
72-
if ((--state & 0x3f) == 0)
76+
if ((--state & 0x1f) == 0)
7377
context = nullptr;
7478
}
75-
return (state & 0x3f);
79+
return (state & 0x1f);
7680
}
7781
// ----------------------------------------------------------------------------
7882

7983
modm::ResumableResult<uint8_t>
80-
modm::platform::SpiMaster{{ id }}::transfer(uint8_t data)
84+
modm::platform::SpiMaster{{ id }}::transfer(const uint8_t data)
8185
{
8286
%% if options["busywait"]
8387
SPDR{{ id }} = data;
@@ -95,75 +99,82 @@ modm::platform::SpiMaster{{ id }}::transfer(uint8_t data)
9599
// 1. waiting to start, and
96100
// 2. waiting to finish.
97101

98-
// MSB != Bit7 ?
99-
if ( !(state & Bit7) )
102+
// MSB != Bit6 ?
103+
if ( !(state & Bit6) )
100104
{
101105
// start transfer by copying data into register
102106
SPDR{{ id }} = data;
103107

104-
// set MSB = Bit7
105-
state |= Bit7;
108+
// set MSB = Bit6
109+
state |= Bit6;
106110
}
107111

108112
// wait for transfer to finish
109113
if (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
110114
return {modm::rf::Running};
111115

112-
data = SPDR{{ id }};
113-
state &= ~Bit7;
114-
return {modm::rf::Stop, data};
116+
state &= ~Bit6;
117+
return {modm::rf::Stop, SPDR{{ id }}};
115118
%% endif
116119
}
117120

118-
modm::ResumableResult<void>
119-
modm::platform::SpiMaster{{ id }}::transfer(const uint8_t *tx, uint8_t *rx, std::size_t length)
121+
modm::ResumableResult<uint16_t>
122+
modm::platform::SpiMaster{{ id }}::transfer(const uint16_t data)
120123
{
121124
%% if options["busywait"]
122-
for (std::size_t index = 0; index < length; index++)
123-
{
124-
modm::ResumableResult<uint8_t> result = transfer(tx ? tx[index] : 0);
125-
if (rx) rx[index] = result.getResult();
126-
}
127-
return {modm::rf::Stop};
125+
SPDR{{ id }} = data >> 8;
126+
127+
// wait for 1rd byte to finish
128+
while (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
129+
;
130+
131+
read = SPDR{{ id }} << 8;
132+
133+
SPDR{{ id }} = data;
134+
135+
// wait for 2nd byte to finish
136+
while (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
137+
;
138+
139+
return {modm::rf::Stop, (uint16_t(read) << 8) | SPDR{{ id }}};
128140
%% else
129141
// this is a manually implemented "fast resumable function"
130142
// there is no context or nesting protection, since we don't need it.
131-
// there are only two states encoded into 1 bit (Bit6 of state):
132-
// 1. initialize index, and
133-
// 2. wait for 1-byte transfer to finish.
143+
// there are only three states encoded into 1 bit (LSB of state):
144+
// 1. waiting to start, and
145+
// 2. waiting to finish.
134146

135-
// we need to globally remember which byte we are currently transferring
136-
static std::size_t index = 0;
147+
// MSB != Bit6 ?
148+
if ( !(state & Bit6) )
149+
{
150+
// start transfer by copying data into register
151+
SPDR{{ id }} = data >> 8;
137152

138-
// we are only interested in Bit6
139-
switch(state & Bit6)
153+
// set MSB = Bit6
154+
state |= Bit6;
155+
}
156+
// MSB != Bit7 ?
157+
if ( !(state & Bit7) )
140158
{
141-
case 0:
142-
// we will only visit this state once
143-
state |= Bit6;
144-
145-
// initialize index and check range
146-
index = 0;
147-
while (index < length)
148-
{
149-
default:
150-
{
151-
// call the resumable function
152-
modm::ResumableResult<uint8_t> result = transfer(tx ? tx[index] : 0);
153-
154-
// if the resumable function is still running, so are we
155-
if (result.getState() > modm::rf::NestingError)
156-
return {modm::rf::Running};
157-
158-
// if rx != 0, we copy the result into the array
159-
if (rx) rx[index] = result.getResult();
160-
}
161-
index++;
162-
}
159+
// wait for 1rd byte to finish
160+
if (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
161+
return {modm::rf::Running};
163162

164-
// clear the state
165-
state &= ~Bit6;
166-
return {modm::rf::Stop};
163+
// store 1rd received byte
164+
read = SPDR;
165+
166+
// start transfer by copying data into register
167+
SPDR{{ id }} = data;
168+
169+
// set MSB = Bit7
170+
state |= Bit7;
167171
}
172+
173+
// wait for 2nd byte to finish
174+
if (!(SPSR{{ id }} & (1 << SPIF{{ id }})))
175+
return {modm::rf::Running};
176+
177+
state &= ~(Bit7 | Bit6);
178+
return {modm::rf::Stop, (uint16_t(read) << 8) | SPDR{{ id }}};
168179
%% endif
169-
}
180+
}

0 commit comments

Comments
 (0)