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