-
Notifications
You must be signed in to change notification settings - Fork 0
/
SPI_SAMD.h
103 lines (92 loc) · 2.55 KB
/
SPI_SAMD.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/*
* SPI.h
*
* Created: 01/07/2021 17:50:40
* Author: GuavTek
*/
#ifndef SPI_SAMD_H_
#define SPI_SAMD_H_
#include <sam.h>
#include "conf_board.h"
#include <port.h>
#include <interrupt.h>
#include "communication_base.h"
struct spi_config_t {
uint8_t sercomNum;
uint8_t dipoVal;
uint8_t dopoVal;
uint64_t speed;
uint32_t pinmux_mosi;
uint32_t pinmux_miso;
uint32_t pinmux_sck;
uint8_t pin_cs[];
};
class SPI_SAMD_C : public communication_base_c
{
public:
virtual uint8_t Transfer(char* buff, uint8_t length, com_state_e state);
virtual inline uint8_t Select_Slave(uint8_t slaveNum, uint8_t enabled);
void Init(const spi_config_t config);
inline void Handler();
SPI_SAMD_C(Sercom* const SercomInstance, uint8_t num_ss) : communication_base_c(num_ss), com(SercomInstance){};
protected:
Sercom* const com;
char* msgBuff;
uint8_t lastSlave;
uint8_t slaveSelected;
uint8_t msgLength;
uint8_t rxIndex;
uint8_t txIndex;
uint8_t* csPin;
};
inline uint8_t SPI_SAMD_C::Select_Slave(uint8_t slaveNum, uint8_t enabled) {
if (enabled && !slaveSelected){
port_pin_set_output_level(csPin[slaveNum], 0);
lastSlave = slaveNum;
slaveSelected = 1;
return 1;
} else if (slaveNum == lastSlave) {
port_pin_set_output_level(csPin[slaveNum], 1);
slaveSelected = 0;
return 1;
}
return 0;
}
// SPI interrupt handler
inline void SPI_SAMD_C::Handler(){
if (com->SPI.INTFLAG.bit.TXC && com->SPI.INTENSET.bit.TXC) {
com->SPI.INTENCLR.reg = SERCOM_SPI_INTENCLR_TXC;
currentState = Idle; // Transmission end
slaveCallbacks[lastSlave]->com_cb();
}
if (com->SPI.INTFLAG.bit.DRE && com->SPI.INTENSET.bit.DRE) {
// Data register empty
if ((currentState == Tx) || (currentState == RxTx)) {
com->SPI.DATA.reg = msgBuff[txIndex];
} else if(currentState == Rx) {
com->SPI.DATA.reg = 0; // Send dummy byte
}
txIndex++;
if (txIndex >= msgLength) {
com->SPI.INTENCLR.reg = SERCOM_SPI_INTENCLR_DRE;
if (currentState == Tx) {
com->SPI.INTENSET.reg = SERCOM_SPI_INTENSET_TXC; // Wait for transmission complete
com->SPI.INTFLAG.reg = SERCOM_SPI_INTFLAG_TXC; // Clear flag
}
}
}
if (com->SPI.INTFLAG.bit.RXC && com->SPI.INTENSET.bit.RXC) {
if ((currentState == Rx) || (currentState == RxTx)) {
msgBuff[rxIndex++] = com->SPI.DATA.reg;
if (rxIndex >= msgLength) {
currentState = Idle;
slaveCallbacks[lastSlave]->com_cb();
//com->SPI.INTENCLR.reg = SERCOM_SPI_INTENCLR_RXC;
}
} else {
volatile uint8_t dumdum = com->SPI.DATA.reg;
}
}
//NVIC_ClearPendingIRQ(SERCOM5_IRQn);
}
#endif /* SPI_SAMD_H_ */