1212 */
1313// ----------------------------------------------------------------------------
1414
15- #include "spi_master{{ id }} .hpp"
15+ #include "spi_master.hpp"
1616
1717#include <avr/io.h>
1818#include <avr/interrupt.h>
2121#include <modm/architecture/interface/atomic_lock.hpp>
2222#include <modm/architecture/interface/interrupt.hpp>
2323
24- uint8_t modm::platform::SpiMaster{{ id }}::count(0);
24+ using State = modm::platform::Spi::State;
25+ using Type = modm::platform::Spi::Type;
2526
26- void* modm::platform::SpiMaster{{ id }}::context(nullptr);
27+ // ----------------------------------------------------------------------------
2728
29+ uint8_t modm::platform::SpiMaster{{ id }}::count(0);
30+ void *modm::platform::SpiMaster{{ id }}::context(nullptr);
2831modm::Spi::ConfigurationHandler
2932 modm::platform::SpiMaster{{ id }}::configuration(nullptr);
3033
31- using State = modm::platform::Spi::State;
32- modm::platform::Spi::State_t state(0);
33-
3434// ----------------------------------------------------------------------------
3535
36- void* tx(nullptr);
37- std::size_t index(0);
38- std::size_t length(0);
36+ modm::platform::Spi::State_t
37+ modm::platform::SpiMaster{{ id }}::state(0);
38+ uint8_t modm::platform::SpiMaster{{ id }}::shift(0);
39+ uint32_t modm::platform::SpiMaster{{ id }}::temp(0);
40+
41+ modm::platform::SpiMaster{{ id }}::unsigned_types_const
42+ modm::platform::SpiMaster{{ id }}::tx{nullptr};
43+ modm::platform::SpiMaster{{ id }}::unsigned_types_const
44+ modm::platform::SpiMaster{{ id }}::tx_end{nullptr};
45+
46+ modm::platform::SpiMaster{{ id }}::unsigned_types
47+ modm::platform::SpiMaster{{ id }}::rx{nullptr};
48+ modm::platform::SpiMaster{{ id }}::unsigned_types
49+ modm::platform::SpiMaster{{ id }}::rx_end{nullptr};
3950
40- void* rx(nullptr);
41- uint16_t temp(0);
4251
4352// ----------------------------------------------------------------------------
4453
45- MODM_ISR(SPI_STC{{ id }}) {
46- // High byte of word is out?
47- if(state.all(State::ByteHigh)) {
48- // Send low byte of word
49- const std::size_t i = state.all(State::AutoIncr) ? index : 0;
50- SPDR{{ id }} = static_cast<uint16_t*>(tx)[i];
51- state.reset(State::ByteHigh);
52- return;
53- }
54+ MODM_ISR(SPI_STC)
55+ {
56+ modm::platform::SpiMaster{{ id }}::isr_handler();
57+ }
5458
55- // Increment index
56- if (++index == length) {
57- if(state.all(State::AutoIncr) and rx) {
58- // TODO Store last received data
59- static_cast<uint8_t*>(rx)[index - 1] = SPDR{{ id }};
59+ void modm::platform::SpiMaster{{ id }}::isr_handler()
60+ {
61+ constexpr State_t state_normal = State::Idle;
62+ constexpr State_t state_repeat = State::Idle | State::Repeat;
63+
64+ switch (state.value) {
65+ case state_normal.value | Type::Byte:
66+ // Store received byte
67+ if (rx.u8)
68+ *rx.u8++ = SPDR{{ id }};
69+ if (++tx.u8 == tx_end.u8)
70+ {
71+ // Job done, disable Interrupt.
72+ SPCR{{ id }} &= ~(1 << SPIE);
73+ return;
6074 }
61-
62- // Job Done, disable Interrupt
63- SPCR{{ id }} &= ~(1 << SPIE{{ id }});
75+ // Transmit next byte
76+ SPDR{{ id }} = *tx.u8;
77+ return;
78+ case state_repeat.value | Type::Byte:
79+ if(++tx.repeat == tx_end.repeat)
80+ {
81+ // Job done, disable Interrupt.
82+ SPCR{{ id }} &= ~(1 << SPIE);
83+ return;
84+ }
85+ // Transmit byte again
86+ SPDR{{ id }} = uint8_t(temp);
87+ return;
88+ case state_normal.value | Type::HalfWord:
89+ if (shift)
90+ {
91+ // Store received byte
92+ if (rx.u8)
93+ *rx.u16 = uint16_t(SPDR{{ id }}) << 8; // << shift
94+ // Transmit next byte
95+ shift = 0;
96+ SPDR{{ id }} = *tx.u16;
97+ return;
98+ }
99+ // Store received byte
100+ if (rx.u16)
101+ *rx.u16++ |= SPDR{{ id }};
102+ if (++tx.u16 == tx_end.u16)
103+ {
104+ // Job done, disable Interrupt.
105+ SPCR{{ id }} &= ~(1 << SPIE);
106+ return;
107+ }
108+ // Transmit next halfword
109+ shift = 1 * 8;
110+ SPDR{{ id }} = *tx.u16 >> shift;
111+ return;
112+ case state_repeat.value | Type::HalfWord:
113+ if (shift)
114+ {
115+ // Transmit next sub-byte
116+ shift = 0;
117+ SPDR{{ id }} = uint16_t(temp);
118+ return;
119+ }
120+ if(++tx.repeat == tx_end.repeat)
121+ {
122+ // Job done, disable Interrupt.
123+ SPCR{{ id }} &= ~(1 << SPIE);
124+ return;
125+ }
126+ // Transmit halfword again
127+ shift = 1 * 8;
128+ SPDR{{ id }} = uint16_t(temp) >> shift;
129+ return;
130+ case state_normal.value | Type::Word:
131+ if (shift)
132+ {
133+ // Store received sub-byte
134+ if (rx.u32)
135+ *rx.u32 |= uint32_t(SPDR{{ id }}) << shift;
136+ // Transmit next sub-byte
137+ shift -= 8;
138+ SPDR{{ id }} = *tx.u32 >> shift;
139+ return;
140+ }
141+ // Store received sub-byte
142+ if (rx.u32) {
143+ *rx.u32++ |= SPDR{{ id }};
144+ *rx.u32 = 0;
145+ }
146+ if (++tx.u32 == tx_end.u32)
147+ {
148+ // Job done, disable Interrupt.
149+ SPCR{{ id }} &= ~(1 << SPIE);
150+ return;
151+ }
152+ // Transmit next word
153+ shift = 3 * 8;
154+ SPDR{{ id }} = *tx.u32 >> shift;
155+ return;
156+ case state_repeat.value | Type::Word:
157+ if (shift)
158+ {
159+ // Transmit next sub-byte
160+ shift -= 8;
161+ SPDR{{ id }} = uint32_t(temp) >> shift;
162+ return;
163+ }
164+ if(++tx.repeat == tx_end.repeat)
165+ {
166+ // Job done, disable Interrupt.
167+ SPCR{{ id }} &= ~(1 << SPIE);
168+ return;
169+ }
170+ // Transmit word again
171+ shift = 3 * 8;
172+ SPDR{{ id }} = uint32_t(temp) >> shift;
64173 return;
65- }
66-
67- // Send next Item
68- const std::size_t i = state.all(State::AutoIncr) ? index : 0;
69- if(state.all(State::Word)) {
70- // TODO Store high byte of word
71- // if(rx)
72- // static_cast<uint16_t*>(rx)[i] = SPDR{{ id }};
73-
74- // Send high byte of word
75- SPDR{{ id }} = static_cast<uint16_t*>(tx)[i] >> 8;
76- state.set(State::ByteHigh);
77- } else {
78- // TODO Store byte
79- // if(rx)
80- // static_cast<uint8_t*>(rx)[i] = SPDR{{ id }};
81- // Send byte
82- SPDR{{ id }} = static_cast<uint8_t*>(tx)[i];
83174 }
84175}
85176
86- template <>
87- void modm::platform::SpiMaster{{ id }}::begin<uint8_t>() {
88- index = 0;
89- state.set(State::Idle);
90- state.reset(State::Word);
91-
92- // start transfer by copying data into register
93- SPDR{{ id }} = static_cast<uint8_t*>(tx)[index];
94- SPCR{{ id }} |= (1 << SPIE{{ id }}); // enable Interrupt
95- }
177+ /* modm::ResumableResult<uint8_t>
178+ modm::platform::SpiMaster{{ id }}::transmit(const uint8_t data)
179+ {
180+ // FIXME does not yet work when called before a regular transmit()
181+ // cause interrupt is not enabled here, witch signales a running condition
182+ // ot the regular transmit.
96183
97- template <>
98- void modm::platform::SpiMaster{{ id }}::begin<uint16_t>() {
99- index = 0;
100- state.set(State::Idle);
101- state.set(State::Word);
102- state.set(State::ByteHigh);
103-
104- // start transfer by copying data into register
105- SPDR{{ id }} = static_cast<uint16_t*>(tx)[index] >> 8;
106- SPCR{{ id }} |= (1 << SPIE{{ id }}); // enable Interrupt
107- }
108- // ----------------------------------------------------------------------------
184+ // Interrupt enabled? transmission in progress!
185+ if (SPCR{{ id }} & (1 << SPIE))
186+ return {modm::rf::Running};
187+
188+ SPDR{{ id }} = data;
189+ // wait for transfer to finish
190+ if (!(SPSR{{ id }} & (1 << SPIF)))
191+ return {modm::rf::Running};
192+
193+ return {modm::rf::Stop, SPDR{{ id }}};
194+ } */
195+
196+ // ---------------------------------------------------------------------------
109197
110198void modm::platform::SpiMaster{{ id }}::initialize(Prescaler prescaler)
111199{
@@ -115,7 +203,6 @@ void modm::platform::SpiMaster{{ id }}::initialize(Prescaler prescaler)
115203 SPSR{{ id }} = (static_cast<uint8_t>(prescaler) & 0x80) ? (1 << SPI2X) : 0;
116204 state = State(0);
117205}
118- // ----------------------------------------------------------------------------
119206
120207uint8_t
121208modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handler)
@@ -142,10 +229,8 @@ modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handl
142229uint8_t
143230modm::platform::SpiMaster{{ id }}::release(void *ctx)
144231{
145- if (ctx == context)
146- {
147- if (--count == 0)
148- context = nullptr;
149- }
232+ if (ctx == context and --count == 0)
233+ context = nullptr;
234+
150235 return count;
151236}
0 commit comments