-
Notifications
You must be signed in to change notification settings - Fork 0
/
FIFOSPI2.c
287 lines (241 loc) · 8.65 KB
/
FIFOSPI2.c
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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/**
* @file: FIFOSPI2.h
* @brief: A 'First In First Out' interrupt driven SPI communication method
* with this device setup as the master.
*
* @author: Connor Martin
* @date: Nov 26, 2013
*
* @preconditions:
* @device:
* -PIC32MX695F512L
*
* @remarks: Currently only supports 2 SPI devices. Some modifications need in
* the setup and IRQ needed to support more. (possibly other places as well)
*
*/
#include "FIFOSPI2.h"
//******************************************************************************
// Local Variables and Typedefs
//******************************************************************************
//Flags
uint8 FIFOSPI2_isRunnning = 0; //Represents if the SPI2 is currently running
int isTransmitsTurn = 1; //used for toggling between transmit and receive
//Send buffers and indexes
int TxBuffer_Index = 0; //Index of how full the send buffer is.
int TxBuffer_TxIndex = 0; //Index of what has been sent
uint8 TxBuffer[FIFOSPI2_BUFFERSIZE]; //Contains the unit8's to send
uint8 TxBufferFlags[FIFOSPI2_BUFFERSIZE]; //Flags for when to drive SS.
int RxBuffer_Index = 0; //Index of how full the receive buffer is
int RxBuffer_ReadIndex = 0; //Index of what has been read out of the buffer
uint8 RxBuffer[FIFOSPI2_BUFFERSIZE]; //Holds all the receive chars from SPI2
//******************************************************************************
//Public Function Definitions
//******************************************************************************
void FIFOSPI2_initialize()
{
//populate the buffers with zeros.
int i = 0;
while (i < FIFOSPI2_BUFFERSIZE)
{
TxBuffer[i] = 0;
TxBufferFlags[i] = 0;
RxBuffer[i] = 0;
i++;
}
//Sets up the pins for SPI for the second device pins
TRISGbits.TRISG8 = 0; //SDO2 write
TRISGbits.TRISG7 = 1; //SDI2 read
TRISGbits.TRISG6 = 0; //SCK2 write
FIFOSPI2_DeviceSSLine1_TriState = 0; //SS2 D1 write //Especially here
FIFOSPI2_DeviceSSLine2_TriState = 0; //SS2 D2 write
// disable all interrupts
INTEnable(INT_SPI2E, INT_DISABLED);
INTEnable(INT_SPI2TX, INT_DISABLED);
INTEnable(INT_SPI2RX, INT_DISABLED);
//Stops and clears SPI2
SPI2CON = 0; // Stops and resets the SPI2.
int rData;
rData=SPI2BUF; // clears the receive buffer
SPI2STATbits.SPIROV = 0; // clear the Overflow
//Set the prescale (Note: ADXL362 recommends 1 MHz to 5 MHz)
SPI2BRG = 7; // use FPB(80MHZ) / 8 = 5Mhz
// F_ SCK = F_PB / (2 * (SPIxBRG + 1))
// F_SCK: SPI clock freq
// F_PB: peripheral clock freq
// SPIxBRG: SPI device baud rate prescalar
//Sets the interupt vector priorty
INTSetVectorPriority(INT_SPI_2_VECTOR, INT_PRIORITY_LEVEL_4);
INTSetVectorSubPriority(INT_SPI_2_VECTOR, INT_SUB_PRIORITY_LEVEL_0);
//Clear any existing interupt events
INTClearFlag(INT_SPI2TX);
INTClearFlag(INT_SPI2RX);
//Check to see if their are bytes queued up to be sent
if (TxBuffer_Index > 0)
{
//Enables the SPI2 IRQ to start sending.
INTEnable(INT_SPI2TX, INT_ENABLED); //SPI2 transmit buffer empty.
}
//Enable SPI2 Interupts
INTEnable(INT_SPI2RX, INT_ENABLED);//SPI2 Receive Done.
//Configure SPI2 and turn it on
SPI2CONbits.CKP = 1; //Clock polarity: Idle state for clock is a
//high level; Active state is a low level
SPI2CONbits.SMP = 1; // Input data sampled at end of data output time
SPI2CONbits.MSTEN = 1; //Master Mode Enable bit
SPI2CONbits.ON = 1; //SPI ON
}
int FIFOSPI2_pushTxQueue(uint8 data[], int length, int deviceSSLine)
{
int i = 0;
//If the send buffer isn't full then add another char
if ((TxBuffer_Index + length) < FIFOSPI2_BUFFERSIZE)
{
// //Adds a token to signify end signal group.
// SendBufferFlags[SendBuffer_Index + length - 1] = 1;
//Add each byte to the buffer
while (i < length)
{
//Populate SendBuuferFlags with which device we a re sending to.
TxBufferFlags[i] = deviceSSLine;
TxBuffer[TxBuffer_Index++] = data[i];
i++;
}
//If SPI2 IRQ is not running then start it
if (FIFOSPI2_isRunnning == 0)
{
FIFOSPI2_isRunnning = 1;
//If the device is on and ready to send
if (SPI2CONbits.ON == 1)
{
//Start sending
INTSetFlag(INT_SPI2TX);
INTEnable(INT_SPI2TX, INT_ENABLED);
}
}
return 1;
}
//Overflow error
else
{
return -1;
}
}
int FIFOSPI2_popRxQueue(uint8 *bytesBuffer)
{
//The receive buffer is empty.
if (RxBuffer_Index == 0)
{
*bytesBuffer = 0;
return 0;
}
//The receiver buffer has entries.
else if (RxBuffer_Index < FIFOSPI2_BUFFERSIZE)
{
char rtn = RxBuffer[RxBuffer_ReadIndex++];
//If all bytes from the buffer have been read.
if (RxBuffer_ReadIndex >= RxBuffer_Index)
{
//Reset the indexs
RxBuffer_ReadIndex = 0;
RxBuffer_Index = 0;
}
*bytesBuffer = rtn;
return 1;
}
//The receive buffer is overflowing.
else if (RxBuffer_Index >= FIFOSPI2_BUFFERSIZE)
{
*bytesBuffer = 0;
return -1;
}
return -3;
}
int FIFOSPI2_rxBufferIndex()
{
return RxBuffer_Index;
}
//******************************************************************************
//Interrupt Request Routines
//******************************************************************************
void __ISR(_SPI_2_VECTOR, IPL4AUTO)__SPI2Interrupt(void)
{
//Receive interupt
if (INTGetFlag(INT_SPI2RX))
{
//If it's RX's turn
if (isTransmitsTurn == 0)
{
//Set the flag so it's TX's turn next
isTransmitsTurn = 1;
//Read byte from buffer
RxBuffer[RxBuffer_Index++] = SPI2BUF;
//Clear Interrupt flag
INTClearFlag(INT_SPI2RX);
//If the current device we are sending to doesn't match the next byte's device
if (TxBufferFlags[TxBuffer_TxIndex] != TxBufferFlags[TxBuffer_TxIndex -1])
{
//TODO: decide if it's better just to deselect all devices.
//Deselect the current device
switch (TxBufferFlags[RxBuffer_Index - 1])
{
case 0:
FIFOSPI2_DeviceSSLine1_PortReg = 1;
FIFOSPI2_DeviceSSLine2_PortReg = 1;
break;
case 1:
FIFOSPI2_DeviceSSLine1_PortReg = 1; //Hi to deselect
break;
case 2:
FIFOSPI2_DeviceSSLine2_PortReg = 1; //Hi to deselect
break;
}
}
//If their are bytes to send
if (TxBuffer_Index > TxBuffer_TxIndex)
{
//Set the TX Interupt flag so that it can send them
INTSetFlag(INT_SPI2TX);
INTEnable(INT_SPI2TX, INT_ENABLED);
}
else
{
//Clear and disable the TX interupt
INTEnable(INT_SPI2TX, INT_DISABLED);
INTClearFlag(INT_SPI2TX);
//update the flag that it's not running anymore.
FIFOSPI2_isRunnning = 0;
//Clear the Send Buffer indecies
TxBuffer_TxIndex = 0;
TxBuffer_Index = 0;
}
}
}
//Transmit interrupt and it is enabled.
if (INTGetFlag(INT_SPI2TX) && INTGetEnable(INT_SPI2TX))
{
//Clear Interrupt flag
//INTClearFlag(INT_SPI2TX);
INTEnable(INT_SPI2TX, INT_DISABLED);
//If it's TX's turn
if (isTransmitsTurn == 1)
{
//Set the flag so it's RX's turn next
isTransmitsTurn = 0;
// //Select the current device
// FIFOSPI2_DeviceSSLine1 = 0;
//Select the current device
switch (TxBufferFlags[TxBuffer_TxIndex])
{
case 1:
FIFOSPI2_DeviceSSLine1_PortReg = 0; //Low to select
break;
case 2:
FIFOSPI2_DeviceSSLine2_PortReg = 0; //Low to select
break;
}
//Send the next byte
SPI2BUF = TxBuffer[TxBuffer_TxIndex++];
}
}
}