12
12
*/
13
13
// ----------------------------------------------------------------------------
14
14
15
- #include "spi_master{{ id }} .hpp"
15
+ #include "spi_master.hpp"
16
16
17
17
#include <avr/io.h>
18
18
#include <avr/interrupt.h>
21
21
#include <modm/architecture/interface/atomic_lock.hpp>
22
22
#include <modm/architecture/interface/interrupt.hpp>
23
23
24
- uint8_t modm::platform::SpiMaster{{ id }}::count(0);
24
+ using State = modm::platform::Spi::State;
25
+ using Type = modm::platform::Spi::Type;
25
26
26
- void* modm::platform::SpiMaster{{ id }}::context(nullptr);
27
+ // ----------------------------------------------------------------------------
27
28
29
+ uint8_t modm::platform::SpiMaster{{ id }}::count(0);
30
+ void *modm::platform::SpiMaster{{ id }}::context(nullptr);
28
31
modm::Spi::ConfigurationHandler
29
32
modm::platform::SpiMaster{{ id }}::configuration(nullptr);
30
33
31
- using State = modm::platform::Spi::State;
32
- modm::platform::Spi::State_t state(0);
33
-
34
34
// ----------------------------------------------------------------------------
35
35
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};
39
50
40
- void* rx(nullptr);
41
- uint16_t temp(0);
42
51
43
52
// ----------------------------------------------------------------------------
44
53
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
+ }
54
58
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;
60
74
}
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;
64
173
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];
83
174
}
84
175
}
85
176
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.
96
183
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
+ // ---------------------------------------------------------------------------
109
197
110
198
void modm::platform::SpiMaster{{ id }}::initialize(Prescaler prescaler)
111
199
{
@@ -115,7 +203,6 @@ void modm::platform::SpiMaster{{ id }}::initialize(Prescaler prescaler)
115
203
SPSR{{ id }} = (static_cast<uint8_t>(prescaler) & 0x80) ? (1 << SPI2X) : 0;
116
204
state = State(0);
117
205
}
118
- // ----------------------------------------------------------------------------
119
206
120
207
uint8_t
121
208
modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handler)
@@ -142,10 +229,8 @@ modm::platform::SpiMaster{{ id }}::acquire(void *ctx, ConfigurationHandler handl
142
229
uint8_t
143
230
modm::platform::SpiMaster{{ id }}::release(void *ctx)
144
231
{
145
- if (ctx == context)
146
- {
147
- if (--count == 0)
148
- context = nullptr;
149
- }
232
+ if (ctx == context and --count == 0)
233
+ context = nullptr;
234
+
150
235
return count;
151
236
}
0 commit comments