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
2526uint8_t
2627modm::platform::SpiMaster{{ id }}::state(0);
2728
29+ uint8_t
30+ modm::platform::SpiMaster::read(0);
31+
2832void *
2933modm::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
7983modm::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