Last active
December 6, 2015 22:20
-
-
Save marioIncandeza/c0447b1da5b5387a2b03 to your computer and use it in GitHub Desktop.
Final Project for Microprocessors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Final Project for EENG 3040 | |
//Patient Position | |
//Mike Johnson & Lindsey Erps | |
//December 2015 | |
#include <xc.h> | |
#include <math.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
// CONFIG1 | |
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN) | |
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled and can be enabled by SWDTEN bit of the WDTCON register) | |
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled) | |
#pragma config MCLRE = ON // RE3/MCLR pin function select bit (RE3/MCLR pin function is MCLR) | |
#pragma config CP = OFF // Code Protection bit (Program memory code protection is disabled) | |
#pragma config CPD = OFF // Data Code Protection bit (Data memory code protection is disabled) | |
#pragma config BOREN = OFF // Brown Out Reset Selection bits (BOR disabled) | |
#pragma config IESO = OFF // Internal External Switchover bit (Internal/External Switchover mode is disabled) | |
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enabled bit (Fail-Safe Clock Monitor is disabled) | |
#pragma config LVP = OFF // Low Voltage Programming Enable bit (RB3 pin has digital I/O, HV on MCLR must be used for programming) | |
// CONFIG2 | |
#pragma config BOR4V = BOR40V // Brown-out Reset Selection bit (Brown-out Reset set to 4.0V) | |
#pragma config WRT = OFF // Flash Program Memory Self Write Enable bits (Write protection off) | |
#define RS RA1 //LCD pin | |
#define RW RA2 //LCD pin | |
#define E RA3 //LCD pin | |
#define _XTAL_FREQ 4000000 //oscillator frequency | |
//table used by numLCD | |
const char lookupTable[] = {'0','1','2','3','4','5','6','7','8','9','.'}; | |
//global declarations for voltage holders | |
int xresult; | |
int yresult; | |
int zresult; | |
/////////////////////////////////////////////////////////////////////////////// | |
// Function: sendCom | |
// General functionality: Sends an instruction to the LCD after the | |
// instruction has been loaded in PORTD | |
// | |
// Returns: void | |
// Arguments: none | |
// Expectations: PORTD has been loaded with a valid LCD instruction, | |
// and PORTA 1-3 have been configured as outputs by | |
// setting TRISA to 0. | |
void sendCom(){ | |
RS = 0; //clear RA1 | |
RW = 0; //clear RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //pause to let things settle | |
E = 1; //set RA3 | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Function: numLCD | |
// General functionality: Prints a number from 0-9 to the LCD. Only one | |
// number is sent to the LCD at a time. The number to | |
// be outputted to the display is passed as an argument | |
// which corresponds to an index in a lookup table | |
// of numbers. The asci value of the number to be displayed | |
// is loaded into PORTD, and then the special sequence | |
// for sending data to the LCD is executed. | |
// | |
// Returns: void | |
// Arguments: int number: the number to be displayed | |
// Expectations: The LCD has been properly configured to receive | |
// data. PORTD must be configured as an output by | |
// setting TRISD to 0. | |
void numLCD(int number){ | |
PORTD = lookupTable[number]; //load the asci value of number into PORTD | |
RS = 1; //set RA1 | |
RW = 0; //clear RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //pause to let bits settle | |
E = 1; //set RA3 | |
} | |
/////////////////////////////////////////////////////////////////////////////// | |
// Function: charLCD | |
// General functionality: Prints a character to the LCD. Only one | |
// character is sent to the LCD at a time. The asci value | |
// of the character to be outputted to the display is | |
// passed as an argument which gets loaded into | |
// PORTD. The data sequence for the LCD is then executed. | |
// | |
// Returns: void | |
// Arguments: char letter: the asci value of the character to be | |
// displayed | |
// Expectations: The LCD has been properly configured to receive | |
// data. PORTD must be configured as an output by | |
// setting TRISD to 0. | |
void charLCD(char letter){ | |
PORTD = letter; //load PORTD with an asci character | |
RS = 1; //set RA1 | |
RW = 0; //clear RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //pause to let bits settle | |
E = 1; //set RA3 | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Function: init | |
// General functionality: Initializes the LCD display, configures the | |
// PIC16F887 to receive serial communications, | |
// disables interrupts, and configures the Ports for | |
// operation in all digital mode. TRISA and TRISD are | |
// cleared (LCD ports), and TRISC is set (RC7 is Rx). | |
// | |
// Returns: void | |
// Arguments: void | |
// | |
// Expectations: None. This function fulfills the expectations of | |
// others. | |
void init(){ | |
ANSEL = 0; //all digital operation | |
ANSELH = 0; //all digital operation | |
TRISA = 0; //configure PORTA all output | |
TRISD = 0; //configure PORTD all output | |
TRISC = 0xFF; //configure PORTC all input; RC7 is Rx | |
PORTA = 0; //clear PORTA | |
PORTC = 0; //clear PORTC | |
PORTD = 0; //clear PORTD | |
PORTD = 0x01; //command to the clear LCD | |
sendCom(); //call sendCom to clock the command into the LCD | |
PORTD = 0x38; //8-bit, 2 line, 5x8 font for the LCD | |
sendCom(); //call sendCom to clock the command into the LCD | |
PORTD = 0x0C; //display on, cursor off, blink off | |
sendCom(); //call sendCom to clock the command into the LCD | |
PORTD = 0x06; //characters rotate right on the LCD | |
sendCom(); //call sendCom to clock the command into the LCD | |
PORTD = 0x80; //move cursor to top of first line | |
sendCom(); //call sendCom to clock the command into the LCD | |
GIE=0; //disable all interrupts | |
BRG16=0; //no 16 bit data | |
BRGH=1; //set BRGH to configure the baud rate | |
SPBRG= 25; //set the baud rate to 9600 | |
SPBRGH=0; //clear to configure the baud rate | |
SYNC=0; //asynchronous operation | |
SPEN=1; //enable the serial port | |
TX9=0; //no 9 bit stuff | |
RX9=0; //no 9 bit stuff | |
__delay_ms(3000); //delay for 3 seconds to give the Xbee some time | |
TXEN=0; //not transmitting | |
CREN=1; //enable reception | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Function: xdisplay | |
// General functionality: This function takes in the double for the value of | |
// the x-axis voltage to be displayed on the LCD. The | |
// function provides general formatting for the | |
// output. This function breaks the value to be | |
// displayed into an array and uses numLCD to output | |
// each element to the display. | |
// | |
// Returns: void | |
// Arguments: x is the voltage between 0-5 volts which | |
// corresponds to the x axis of an accelerometer. | |
// Expectations: The function expects to be passed a double between | |
// 0-5. The LCD should already be configured as well | |
// as the associated Ports. The function will put a | |
// decimal after the first number so unless that's | |
// appropriate, don't use this function. | |
void xdisplay(double x){ | |
const char xform[] = {'('}; //formatting parenthesis | |
for(int k = 0; k<1; k++){ | |
PORTD = xform[k]; //load the character into the LCD | |
RS = 1; //set RA1 | |
RW = 0; //clear RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //let the bits settle | |
E = 1; //set RA3 | |
} | |
double integral; //the modf function requires there be a place | |
//to store the whole part of the number it splits | |
double fractional = modf(x,&integral); //split whole and fractional | |
int shifted = fractional*100.0; //shift the decimal to the right | |
int typeConversion = shifted; //mysteriously necessary | |
/* extract each digit */ | |
int c = 1; //counter | |
int numberArray[]; //array in which to store decimal numbers | |
while (c >= 0){ | |
numberArray[c] = typeConversion % 10; //slice off the first digit and put it in the array | |
typeConversion /= 10; //knock that digit off and repeat this process until there's nothing left | |
c--; //the places parameter comes in handy here since C doesn't just know how long a given array is | |
} //i'm putting the least significant digit at the end of the array because we want to display that one last | |
numLCD(integral); //display ones place | |
numLCD(10); //display decimal point | |
for(int i = 0; i<2; i++ ){ | |
numLCD(numberArray[i]); //output the digits in the array to the LCD | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Function: ydisplay | |
// General functionality: This function takes in the double for the value of | |
// the y-axis voltage to be displayed on the LCD. The | |
// function provides general formatting for the | |
// output. This function breaks the value to be | |
// displayed into an array and uses numLCD to output | |
// each element to the display. | |
// | |
// Returns: void | |
// Arguments: y is the voltage between 0-5 volts which | |
// corresponds to the y axis of an accelerometer. | |
// Expectations: The function expects to be passed a double between | |
// 0-5. The LCD should already be configured as well | |
// as the associated Ports. The function will put a | |
// decimal after the first number so unless that's | |
// appropriate, don't use this function. | |
void ydisplay(double y){ | |
const char yform[] = {','}; //formatting characters | |
for(int k = 0; k<1; k++){ | |
PORTD = yform[k]; //load the character into PORTD | |
RS = 1; //set RA1 | |
RW = 0; //clear RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //pause to let bits settle | |
E = 1; //set RA3 | |
} | |
double integral; //the modf function needs somewhere to put the whole part of the number | |
double fractional = modf(y,&integral); //split that double | |
int shifted = fractional*100.0; //shift the decimal place to the right | |
int typeConversion = shifted; //mysteriously necessary | |
/* extract each digit */ | |
int c = 1; //counter | |
int numberArray[]; //array to store individual digits | |
while (c >= 0){ | |
numberArray[c] = typeConversion % 10; //slice off the first digit and put it in the array | |
typeConversion /= 10; //knock that digit off and repeat this process until there's nothing left | |
c--; //the places parameter comes in handy here since C doesn't just know how long a given array is | |
} //i'm putting the least significant digit at the end of the array because we want to display that one last | |
numLCD(integral); //display the ones digit | |
numLCD(10); //display a decimal point | |
for(int i = 0; i<2; i++ ){ | |
numLCD(numberArray[i]); //output the digits in the array to the LCD | |
} | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Function: zdisplay | |
// General functionality: This function takes in the double for the value of | |
// the z-axis voltage to be displayed on the LCD. The | |
// function provides general formatting for the | |
// output. This function breaks the value to be | |
// displayed into an array and uses numLCD to output | |
// each element to the display. | |
// | |
// Returns: void | |
// Arguments: z is the voltage between 0-5 volts which | |
// corresponds to the z axis of an accelerometer. | |
// Expectations: The function expects to be passed a double between | |
// 0-5. The LCD should already be configured as well | |
// as the associated Ports. The function will put a | |
// decimal after the first number so unless that's | |
// appropriate, don't use this function. | |
void zdisplay(double z){ | |
const char zform[] = {','}; //formatting character | |
for(int k = 0; k<1; k++){ | |
PORTD = zform[k]; //load PORTD with the asci character | |
RS = 1; //set RA1 | |
RW = 0; //clear RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //pause to let the bits settle | |
E = 1; //set RA3 | |
} | |
double integral; //modf needs a place to put the integer | |
double fractional = modf(z,&integral); //split the whole and fractional | |
int shifted = fractional*100.0; //shift the decimal to the right | |
int typeConversion = shifted; //mysteriously necessary | |
/* extract each digit */ | |
int c = 1; //counter | |
int numberArray[]; //an array to store the digits | |
while (c >= 0){ | |
numberArray[c] = typeConversion % 10; //slice off the first digit and put it in the array | |
typeConversion /= 10; //knock that digit off and repeat this process until there's nothing left | |
c--; //the places parameter comes in handy here since C doesn't just know how long a given array is | |
} //i'm putting the least significant digit at the end of the array because we want to display that one last | |
numLCD(integral); //display the ones digit | |
numLCD(10); //display a decimal point | |
for(int i = 0; i<2; i++ ){ | |
numLCD(numberArray[i]); //output the digits in the array to the LCD | |
} | |
PORTD = ')'; //formatting character | |
RS = 1; //set RA1 | |
RW = 0; //set RA2 | |
E = 0; //clear RA3 | |
__delay_us(50); //pause to allow the bits to settle | |
E = 1; //set RA3 | |
} | |
//////////////////////////////////////////////////////////////////////////////// | |
// Function: main | |
// General functionality: This function manages the datastream coming from | |
// the accelerometer of a patient. The function waits | |
// to receive 0xFF and then puts the data received in | |
// RCREG into an array called datastream. The data in | |
// datastream is used to calculate the accelerometer | |
// voltages for the three axes. A checksum is also | |
// calculated to ensure that all of the data has been | |
// properly received. The function uses this info to | |
// make a prediction about the position of the patient. | |
// If the checksums do not match, "Bad packet" is | |
// displayed on the LCD. | |
// | |
// Returns: void | |
// Arguments: void | |
// Expectations: This function expects to receive serial | |
// transmissions which begin with 0xFF. | |
void main(){ | |
init(); //call the initialization function | |
char datastream[8]; //initialize a character array to store the data transmission | |
while(1){ | |
while(RCREG!=0xFF); //wait until the first character comes back around | |
PORTD = 0x01; //clear the LCD | |
sendCom(); //send the command to the LCD | |
for (int k = 0; k<8; k++){ | |
while(!RCIF); //wait until the transmission is finished | |
datastream[k] = RCREG;//store the data received in in RCREG in the datastream | |
} | |
xresult = 256*datastream[0] + datastream[1]; //compute the 10 bit x-axis value | |
yresult = 256*datastream[2] + datastream[3]; //compute the 10 bit y-axis value | |
zresult = 256*datastream[4] + datastream[5]; //compute the 10 bit z-axis value | |
//compute the value of the first six bytes of data | |
int check = datastream[0] + datastream[1] + datastream[2] + datastream[3] + datastream[4] + datastream[5]; | |
int checksum = 256*datastream[6] + datastream[7];//compute the checksum | |
if (check == checksum){ //check to see if the data has been received without error | |
double xOut = (xresult/1023.0)*5.0; //convert xresult to value btw 0-5 | |
double yOut = (yresult/1023.0)*5.0; //convert yresult to value btw 0-5 | |
double zOut = (zresult/1023.0)*5.0; //convert zresult to value btw 0-5 | |
PORTD = 0x80; //set the cursor to the beginning of the first line | |
sendCom(); //send command to LCD | |
xdisplay(xOut); //pass xOut to the function xdisplay | |
ydisplay(yOut); //pass yOut to the function ydisplay | |
zdisplay(zOut); //pass zOut to the function zdisplay | |
PORTD = 0xC0; //set the cursor to the beginning of the second line | |
sendCom(); //send command to the LCD | |
if (xOut < 1.545){ //is there less than 0g on the x axis? | |
const char A[]="Position A"; //if so, patient may be in position A | |
for (int a = 0; a<10; a++){ | |
charLCD(A[a]); //display A | |
} | |
} | |
else if (xOut > 1.755){ //is there more than 0g on the x axis? | |
const char D[]="Position D"; //if so, patient may be in position D | |
for (int d = 0; d<10; d++){ | |
charLCD(D[d]); //display D | |
} | |
} | |
else if (yOut < 1.545){ //is there less than 0g on the y axis? | |
const char C[]="Position C"; //if so, patient may be in position C | |
for (int c = 0; c<10; c++){ | |
charLCD(C[c]); //display C | |
} | |
} | |
else if (yOut > 1.755){ //is there more than 0g on the y axis? | |
const char B[]="Position B"; //if so, patient may be in position B | |
for (int b = 0; b<10; b++){ | |
charLCD(B[b]); //display B | |
} | |
} | |
else if (zOut < 1.545){ //is there less than 0 g on the z axis? | |
const char F[]="Position F"; //if so, patient may be in position F | |
for (int f = 0; f<10; f++){ | |
charLCD(F[f]); //display F | |
} | |
} | |
else { | |
const char Ee[]="Position E"; //otherwise, patient is in position E | |
for (int e = 0; e<10; e++){ | |
charLCD(Ee[e]); //display E | |
} | |
} | |
} | |
else { //if there was an error in transmission | |
PORTD = 0x80; //set the cursor to the beginning of the first line | |
sendCom(); //send command to LCD | |
const char packet[]="Bad packet"; //error message | |
for (int p = 0; p<10; p++){ | |
charLCD(packet[p]); //display error message | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment