0% found this document useful (0 votes)
103 views

#Include #Include: "Spi.H" "Digitalio.H"

This document contains code for initializing two SPI modules on a microcontroller - SPI1 for receiving data and SPI2 for transmitting data. It configures the pin mappings, baud rate, data width, and interrupt handling for both SPI modules. Upon receiving data on SPI1, an interrupt will trigger to parse the data packet and post update events for the bar graph and display services.

Uploaded by

api-552271981
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
103 views

#Include #Include: "Spi.H" "Digitalio.H"

This document contains code for initializing two SPI modules on a microcontroller - SPI1 for receiving data and SPI2 for transmitting data. It configures the pin mappings, baud rate, data width, and interrupt handling for both SPI modules. Upon receiving data on SPI1, an interrupt will trigger to parse the data packet and post update events for the bar graph and display services.

Uploaded by

api-552271981
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

#include "spi.

h"
#include "DigitalIO.h"

// Hardware
#include <xc.h>
#include <proc/p32mx170f256b.h>
#include <sys/attribs.h> // for ISR macros
#include "DigitalIO.h"//Hardware abstraction layer
#include "Hardware_Configure.h"

// Event & Services Framework


#include "ES_Configure.h"
#include "ES_Framework.h"
#include "ES_DeferRecall.h"
#include "ES_ShortTimer.h"
#include "ES_Port.h"

//Bar graph service


#include "BarGraphService.h"

//Display Service
#include "DisplayService.h"
/*----------------------------- Module Defines ----------------------------*/

/*----------------------------- Module Variables --------------------------*/

/*ByteArray holds contents to sent by Display PIC (minus delimiter bytes).


*Structured as follows:
Byte: Contents: Possible Value(s):
0 Start Delimiter MSB 0xFF
1 Start Delimiter LSB 0xFE
2 Joystick X MSB 0-3
3 Joystick X LSB 0-255
4 Joystick Y MSB 0-3
5 Joystick Y LSB 0-255
6 Weapons Range 0-128
7 Hull Capacity 0-100
8 Shield Capacity 0-200
9 Weapons Capacity 0-200
10 Navigation Power 0-64
11 Ship X MSB (our ship) 0-255
12 Ship X LSB 0-255
13 Ship Y MSB 0-255
14 Ship Y LSB 0-255
15 Alive Byte 0-1
*/
static volatile uint8_t byteArray[PACKET_LENGTH];//Holds SPI Rx packet

//Keeps track of which byte we're on in the packet


static volatile uint8_t byteIndex;

//Boolean used to indicate if we're in middle of reading a packet


static volatile bool inMessage = 0;
1
//Contains human-readable values from 0-10 that will be displayed on each
graph
static volatile uint8_t graphArray[NUM_GRAPHS];

//Contains [MSB LSB MSB LSB] of Joystick X and Y ADC values


static volatile uint8_t aimArray[AIM_LENGTH];

//Contains [MSB LSB MSB LSB] of our ship's X and Y coords


static volatile uint8_t shipArray[AIM_LENGTH];

/***************************** GET GRAPH VALS


*******************************/
uint8_t * getGraphVals(void){

/*Map the full value range to 0-10 for each parameter*/


//Relevant ByteArray Indexes:
// 6 Hull Capacity 0-100
// 7 Shield Capacity 0-200
// 8 Weapons Range 0-128
// 9 Navigation Power 0-64*/
graphArray[3] = byteArray[POS_GRAPH]/10; //Hull
graphArray[2] = byteArray[POS_GRAPH+1]/20;//Shield
graphArray[1] = byteArray[POS_GRAPH+2]/20;//Weapons Cap
graphArray[0] = byteArray[POS_GRAPH+3]/6; //Nav Power
// #ifdef SPI_DEBUG
// printf("\n\r");
// for(uint8_t i = 0; i< NUM_GRAPHS; i++){
// printf("%d ", graphArray[i]);
// }
// #endif //SPI_DEBUG
return graphArray;//Return pointer to 1st elm of graphArray
}

/***************************** GET Aim VALS *******************************/


uint8_t * getAimVals(void){
for(uint8_t i = 0; i < AIM_LENGTH; i++){//For each aim value
/*Grab joystick or range data from byteArray*/
aimArray[i] = byteArray[POS_AIM+i];
}
return aimArray;//Return pointer to 1st elm of aimArray
}

/***************************** GET location VALS


*****************************/
uint8_t * getShipVals(void){
for(uint8_t i = 0; i < SHIP_LENGTH; i++){
/*Grab ship data from byteArray*/
shipArray[i] = byteArray[POS_SHIP+i];
}
2
return shipArray;//Return pointer to 1st elm of shipArray
}

/***************************************************************************
Interrupt Service Routines
***************************************************************************/
void __ISR(_SPI1_VECTOR, IPL7SOFT) SPI_Handler(void){
volatile uint8_t thisByte;//Holds contents of RX buffer
volatile ES_Event_t thisEvent;//Will be posted if an update is required

if(IFS1bits.SPI1RXIF){//If SPI1 rx flag is active

thisByte = SPI1BUF;//Read register

if(thisByte == SD_MSB && !inMessage){//This should be the first byte


byteIndex = 0; //Reset byte index
inMessage = true; //We're starting our message
byteArray[0] = thisByte;//Save first byte
}
if(inMessage){//If we're parsing the array
if(byteIndex == 1){//If we're on second byte
byteArray[1] = thisByte;//Save second byte
if(thisByte != SD_LSB){ //If it's not the start delimiter LSB
inMessage = false; //Start looking for new delimiter
}
}
if(byteIndex >= POS_AIM && byteIndex < PACKET_LENGTH){//Packet data:
byteArray[byteIndex] = thisByte;//Save buffer contents into array
}
if(byteIndex >= PACKET_LENGTH-1){//If EOM

/*If we got to this point we had a valid update*/


thisEvent.EventType = ES_GRAPH_UPDATE;
PostBarGraphService(thisEvent);//Post graph update
thisEvent.EventType = ES_OUR_SHIP_UPDATE;
PostDisplayService(thisEvent);//Post aim/ coordinates update

inMessage = false; //Done with message

// printf("\n\r");
// printf("%d ",thisByteArr[0]);
// printf("%d ",thisByteArr[1]);
// volatile uint8_t i = 0;
// for(i = 0; i<DATA_LENGTH; i++){
// printf("%d ", byteArray[i]);
// }
}

byteIndex++;//Moving onto next byte...


}
/*Do this last or you will be cursed with SPI overrun!*/
IFS1CLR = _IFS1_SPI1RXIF_MASK; //Clear SPI1 Receive Complete Flag.
}
}
3
/****************************************************************************
Function
SPI_Init
Parameters
bitRate, bitWidth, mode (0 for slave, 1 for master)
Returns
void
Description
set up the SPI system for use. Set the clock phase and polarity, master
mode
clock source, baud rate, SS control, transfer width (8-bits)
Notes
don't forget to map the pins & set up the TRIS not only for the SPI pins
but also for the DC (RB13) & Reset (RB12) pins
Author: Ethan Kurteff 2/10/21

****************************************************************************/
void SPI_Init(uint32_t bitRate, uint8_t bitWidth){
/*MAKE SURE YOU CONFIGURE PINS AS INPUT/ OUTPUT BEFORE RUNNING SPI_INIT!*/

/*SPI ONE INPUT-----------------------*/


/*Configure SPI1 for receiving data*/
SDI1R = 0b0011;//Map SDI1 to RB11 (MOSI_1)
SS1R = 0b0100;//Map SS1 to RB7
//(RB14 is always SCK_1)

/*Reset and the SPI module for protocol-specific settings.*/


SPI1CONbits.ON = 0;//Stop and reset SPI1 module by clearing the ON bit
SPI1BUF = 0;//Clear the receive buffer

/*Calculate baud rate divisor to get our desired clock rate or below.
* Assumes PB clock (FPB) is 20MHz
*FSCK = FPB/(2*(BRG+1) = 20E6/(2*(999+1))*/
/* IF PBCLK is evenly divisible by desired freq*/
if(PBCLK%(2*bitRate)==0) SPI1BRG = PBCLK/(2*bitRate)-1;//Calculate BRG exactly
else SPI1BRG = PBCLK/(2*bitRate);//Step the speed down one notch

SPI1CONbits.MSTEN = 0;//Set the PIC's SPI1 module to slave mode

/*Change the SPI desired settings for the specific protocol*/


SPI1CONbits.FRMPOL = 0;//Slave Select pulse is active low
SPI1CONbits.CKP = 0;//Set clock polarity to active low (1) //active high = 0
SPI1CONbits.CKE = 1;//Start reading data on second clock edge (0)

/*Configure bit width*/


if(bitWidth == 32) SPI1CONbits.MODE32 = 1;//Data width will be 32 bits
else if (bitWidth == 16)
{
SPI1CONbits.MODE32 = 0;//Data width will not be 32 bit
SPI1CONbits.MODE16 = 1;//Set data width to 16 bit
}
else if (bitWidth == 8)
4
{
SPI1CONbits.MODE32 = 0;//Data width will not be 32 bit
SPI1CONbits.MODE16 = 0;//Set data width to 8 bits
}

/*SPI TWO OUTPUT-----------------------*/


/*Configure SPI2 for driving LED Bar Graph*/
RPB8R = 0b0100; //Map RB8 to SDO_2

/*Reset and the SPI module for protocol-specific settings.*/


SPI2CONbits.ON = 0;//Stop and reset SPI1 module by clearing the ON bit
SPI2BUF = 0;//Clear the receive buffer

/*Calculate baud rate divisor to get our desired clock rate or below.
* Assumes PB clock (FPB) is 20MHz
*FSCK = FPB/(2*(BRG+1) = 20E6/(2*(999+1))*/
/* IF PBCLK is evenly divisible by desired freq*/
if(PBCLK%(2*bitRate)==0) SPI2BRG = PBCLK/(2*bitRate)-1;//Calculate BRG exactly
else SPI2BRG = PBCLK/(2*bitRate);//Step the speed down one notch

SPI2CONbits.MSTEN = 1;//Set the PIC's SPI2 module to master mode

/*Change the SPI desired settings for the specific protocol*/


SPI2CONbits.FRMPOL = 0;//Slave Select pulse is active low
SPI2CONbits.CKP = 0;//Set clock polarity to active high
SPI2CONbits.CKE = 1;//Start reading data on first clock edge

/*Configure bit width*/


if(bitWidth == 32) SPI2CONbits.MODE32 = 1;//Data width will be 32 bits
else if (bitWidth == 16)
{
SPI2CONbits.MODE32 = 0;//Data width will not be 32 bit
SPI2CONbits.MODE16 = 1;//Set data width to 16 bit
}
else if (bitWidth == 8)
{
SPI2CONbits.MODE32 = 0;//Data width will not be 32 bit
SPI2CONbits.MODE16 = 0;//Set data width to 8 bits
}

/*Set up SPI interrupts*/


//Write the SPI1 interrupt priority/sub-priority bits
IPC7bits.SPI1IP = 7;//Set priority to max level

//Clear interrupt flags


IFS1CLR = _IFS1_SPI1RXIF_MASK; //Clear SPI1 Receive Complete Flag
SPI1STATbits.SPIROV = 0;//Clear the SPI2 receive overflow flag bit

//Enable SPI1 interrupts


IEC1bits.SPI1RXIE = 1;//Enable SPI1 receive interrupt

//Enable interrupts globally


5
INTCONbits.MVEC = 1; //Set up for multiple interrupt vectors
__builtin_enable_interrupts();//Globally enable interrupts

/*TURN IT ON!*/
SPI1CONbits.ON = 1;//Turn on SPI1
SPI2CONbits.ON = 1;//Turn on SPI2

//printf("\n\rSPI 1 & 2 Setup COMPLETE!");


}

/****************************************************************************
Function
SPI_Tx
Parameters
uint8_t data the 8-bit value to be sent out through the SPI
Returns
void
Description
write the data to the SPIxBUF and then wait for it to go out (SPITBF)
Notes
don't forget to read the buffer after the transfer to prevent over-runs

****************************************************************************/
void SPI_Tx(uint8_t data){
while(SPI2STATbits.SPITBF);//Wait while tx buffer is full
SPI2BUF = data;//Write data to SPI xmit buffer
while(!SPI2STATbits.SRMT);//Wait until shift register is empty
SPI2BUF;//Read buffer to clear/prevent over-runs
}

/****************************************************************************
Function
SPI_TxBuffer
Parameters
uint8_t *buffer, a pointer to the buffer to be transmitted
uint8_t length the number of bytes in the buffer to transmit
Returns
void
Description
loop through buffer calling SPI_Tx for each element in the buffer
Notes

****************************************************************************/
void SPI_TxBuffer(uint8_t *buffer, uint8_t length){
uint8_t index = 0;//Determines our position in buffer
while(index < length)//While we are in bounds of buffer array
{
SPI_Tx(*(buffer+index));//Transmit the index(th) element of buffer
index++;//Move on to next element
}
}

You might also like