Skip to content

Instantly share code, notes, and snippets.

@marioIncandeza
Last active December 6, 2015 22:20
Show Gist options
  • Save marioIncandeza/c0447b1da5b5387a2b03 to your computer and use it in GitHub Desktop.
Save marioIncandeza/c0447b1da5b5387a2b03 to your computer and use it in GitHub Desktop.
Final Project for Microprocessors
//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