new update for c code(deliverable 1)

0 views
Skip to first unread message

Hao Zhang

unread,
Oct 6, 2011, 9:08:50 PM10/6/11
to 3K04 project grp
/* Turn off watchdog timer */
#pragma config WDT=OFF

/* Set oscillator mode to be HS (high speed) */
#pragma config OSC=HS


#include <p18cxxx.h>
#include <delays.h>
#include <math.h>


/* Frequency of the oscillator */
#define FOSC 4000000

/* Baud rate for serial communication */
#define BAUD_RATE 19200

/* Timer0 interval in microseconds */
#define TIMER0 500000


/* ANSI escape sequences */
#define ANSI_ESC "\033["
#define ANSI_CLEAR_SCREEN (ANSI_ESC"2J")
#define ANSI_CLEAR_LINE (ANSI_ESC"K")
#define ANSI_SAVE_CURSOR (ANSI_ESC"s")
#define ANSI_RESTORE_CURSOR (ANSI_ESC"u")


/* A simple cyclic buffer implementation */
/* The size of such buffer is 2^5 = 32 */
#define BUF_BITS 5
#define BUF_SIZE (1 << BUF_BITS)
#define BUF_MASK (BUF_SIZE - 1)

/* Initialize buffer */
#define BUF_INIT(buf) \
do { \
(buf).head = (buf).tail = 0; \
} while (0)

/* Pop an element from the head of the FIFO buffer */
#define BUF_GET(buf) \
((buf).data[(buf).head++ & BUF_MASK])

/* Append an element into the end of the FIFO buffer */
#define BUF_ADD(buf, c) \
do { \
(buf).data[(buf).tail & BUF_MASK] = (c); \
(buf).tail++; \
} while (0)

/* Append an array of elements into the buffer */
#define BUF_ADDSTR(buf, str) \
do { \
char __i; \
for(__i = 0; (str)[__i]; __i++) { \
BUF_ADD(buf, (str)[__i]); \
} \
} while(0)

/* Test if the buffer is empty */
#define BUF_EMPTY(buf) \
(!(((buf).tail ^ (buf).head) & BUF_MASK))

/* Test if the buffer is full */
#define BUF_FULL(buf) \
(!((((buf).tail + 1) ^ (buf).head) & BUF_MASK))

/* Return the number of elements in the buffer */
#define BUF_LEN(buf) \
(((buf).tail - (buf).head) & BUF_MASK)


/* A struct for the cyclic buffer */
struct buffer {
char data[BUF_SIZE];
volatile char head;
volatile char tail;
};


/* Sending buffer */
struct buffer txbuf;
/* Receiving buffer */
struct buffer rcbuf;


/* Interrupt handler function */
void intr_handler(void);

/* Setting interrupt entrance on PIC18 */
#pragma code intr_section = 0x8
void intr_entry(void) {
_asm goto intr_handler _endasm
}
#pragma code


/* Interrupt handler function */
#pragma interrupt intr_handler
void intr_handler(void) {
/* If the microcontroller received a byte */
if (PIR1bits.RCIF) {
/* Add the byte into receiving buffer */
BUF_ADD(rcbuf, RCREG);
}
/* If the microcontroller sent a byte */
if (PIR1bits.TXIF) {
/* If there is nothing to send (the sending buffer is empty)
*/
if (BUF_EMPTY(txbuf)) {
/* Turn off sending interrupt */
PIE1bits.TXIE = 0;
} else {
/* Send the first byte in the sending buffer */
TXREG = BUF_GET(txbuf);
}
}
if (INTCONbits.TMR0IF) {
//INTCONbits.TMR0IF = 0;
INTCONbits.TMR0IE = 0;
}
}

/* Initialize serial port */
void uart_init(void) {
unsigned int i;

/* Set baud rate */
/* BRGH mode */
TXSTAbits.BRGH = 1;
/* BRG16 mode */
BAUDCONbits.BRG16 = 0;
/* Value of the SPBRG registor for the given baud rate. Check
datasheet
to make sure that the combination of BAUD_RATE,FOSC,BRGH,BRG16
produces
a valid SPBRG. */
i = 64 >> ((TXSTAbits.BRGH + BAUDCONbits.BRG16)
* 2);
i = FOSC / BAUD_RATE / i - 1;
SPBRGH = i >> 8;
SPBRG = i & 0xFF;

/* Configure the pins for UART */
TRISCbits.TRISC6 = 1;
TRISCbits.TRISC7 = 1;

/* Enable serial port */
RCSTAbits.SPEN = 1;
/* Enable asynchronous mode */
TXSTAbits.SYNC = 0;
/* Enable transmission (sending) */
TXSTAbits.TXEN = 1;
/* Enable receiving */
RCSTAbits.CREN = 1;

/* Enable interrupt priority */
RCONbits.IPEN = 1;
/* Set high priority for sending and receiving interrupt */
IPR1bits.RCIP = 1;
IPR1bits.TXIP = 1;
/* Enable high priority interrupt */
INTCONbits.GIEH = 1;
/* Enable receiving interrupt */
PIE1bits.RCIE = 1;

/* Initialize receiving buffer */
BUF_INIT(rcbuf);
/* Initialize sending buffer */
BUF_INIT(txbuf);
}

/* Initialize Timer0 */
void timer0_init(void) {
/* Clock periods needed to get the time interval */
unsigned long i = (float)FOSC * TIMER0 / 1000000;

/* TMR0ON T08BIT T0CS T0SE PSA T0PS2 T0PS1 T0PS0 */
T0CON = 0b10000000;

/* Set prescaler */
if (i >> 16) {
for (i >>= 1; i >> 16; i >>= 1, T0CON++);
} else {
T0CON |= 8;
}

/* Set TMR0 = 65536 - i, so after i periods, an interrupt will
fire up */
i = (0xFFFF ^ i) + 1;
TMR0H = i >> 8;
TMR0L = i & 0xFF;

/* Clear TMR0IF flag */
INTCONbits.TMR0IF = 0;
/* Enable Timer0 interrupt */
INTCONbits.TMR0IE = 1;
}

/* Initialize ventricle sense */
void sense_init(void) {
/* Set ventricle sense (pin33) to be input */
TRISBbits.TRISB0 = 1;
}

/* Initialize A/D converter */
void adc_init(void) {
/* Enable ventricle sensing (MICRO_VENT_SENSE_BLANK_CNTL) */
TRISDbits.TRISD4 = 0;
PORTDbits.RD4 = 1;

/* Enable atrial sensing (MICRO_ATRIAL_SENSE_BLANK_CNTL) */
TRISDbits.TRISD5 = 0;
PORTDbits.RD5 = 1;

/* Set SCK to be output pin */
TRISCbits.TRISC3 = 0;
/* Set SDI to be input pin */
TRISCbits.TRISC4 = 1;
/* Set SDO to be output pin */
TRISCbits.TRISC5 = 0;
/* Set SS to be input pin */
TRISAbits.TRISA5 = 1;
}

/* Read a number from A/D converter */
unsigned int adc_get(void) {
unsigned int c = 0;
char i;

for (i = 0; i < 16; i++) {
/* Flip clock line (SCK) */
PORTCbits.SCK = 0;
PORTCbits.SCK = 1;
/* Shift buffer */
c <<= 1;
/* Read a bit and place it at the end of the buffer */
c |= PORTCbits.SDI;
}

return c;
}

/* Wait for A/D converter to be ready for reading */
void adc_start(void) {
/* Ask if A/D converter is ready */
PORTCbits.SDO = 0;
PORTCbits.SCK = 0;
PORTCbits.SCK = 1;
PORTCbits.SDO = 1;

/* Wait for reply */
while (!PORTCbits.SDI);
}

/* Turn off the conversation with A/D converter */
void adc_stop(void) {
PORTCbits.SCK = 0;
PORTCbits.SDO = 0;
}

/* Convert an integer to string, similar to printf("%0nd", i) */
char *intstr(unsigned int i, char n) {
static char buf[6];
char j;

/* Get the least significant digit */
buf[4] = '0' + i % 10;
buf[5] = 0;

/* Get the rest digits */
for (i /= 10, j = 3; i; i /= 10, j--) {
buf[j] = '0' + i % 10;
}

/* Fill the leading zeros */
n = (n >= 4 - j) ? n : (4 - j);
for (; j > 4 - n; j--) {
buf[j] = '0';
}

return &buf[j + 1];
}

/* Timer0 event handler */
void on_timer0(void) {
char buf[6];
unsigned int d;
float v;

/* Reset Timer0 */
timer0_init();

/* Start conversation with A/D converter */
adc_start();

/* Save the current cursor position */
BUF_ADDSTR(txbuf, ANSI_SAVE_CURSOR);

/* Get ventricle voltage */
v = 5.0 * adc_get() / 65535;
/* Print integer part */
BUF_ADDSTR(txbuf, intstr(v, 0));
v = modf(v, (void *)0) * 1000;
/* Print decimal point */
BUF_ADD(txbuf, '.');
/* Print decimal part */
BUF_ADDSTR(txbuf, intstr(v, 3));
BUF_ADD(txbuf, ' ');

/* Get atrial voltage */
v = 5.0 * adc_get() / 65535;
/* Print integer part */
BUF_ADDSTR(txbuf, intstr(v, 0));
v = modf(v, (void *)0) * 1000;
/* Print decimal point */
BUF_ADD(txbuf, '.');
/* Print decimal part */
BUF_ADDSTR(txbuf, intstr(v, 3));
BUF_ADD(txbuf, ' ');

/* Stop conversation with A/D converter */
adc_stop();

/* Print ventricle sensing bit */
BUF_ADD(txbuf, '0' + PORTBbits.RB0);
BUF_ADD(txbuf, '\n');

/* Clear rest of the line */
BUF_ADDSTR(txbuf, ANSI_CLEAR_LINE);
/* Restore cursor position */
BUF_ADDSTR(txbuf, ANSI_RESTORE_CURSOR);

/* Enable sending interrupt */
PIE1bits.TXIE = 1;
}

/* UART event handler */
void on_uart(void) {
char c;
char d;

BUF_ADDSTR(txbuf, "\n\r");
/* Read one byte from the receiving buffer */
c = BUF_GET(rcbuf);
/* Get the first hex code of the byte */
d = c >> 4;
d += (d < 10) ? '0' : ('a' - 10);
/* Put the code in sending buffer */
BUF_ADD(txbuf, d);
/* Get the second hex code of the byte */
d = c & 0xF;
d += (d < 10) ? '0' : ('a' - 10);
/* Put the code in sending buffer */
BUF_ADD(txbuf, d);
BUF_ADD(txbuf, ' ');

/* Now the sending buffer is non-empty, we enable
transmission interrupt to send the contents in sending
buffer */
PIE1bits.TXIE = 1;
}

/* Main entrance */
void main(void) {

/* Initialize */
sense_init();
uart_init();
timer0_init();
adc_init();
char sData[16];
char checkSum;

/* Clear screen and append a string to sending buffer */
BUF_ADDSTR(txbuf, ANSI_CLEAR_SCREEN);
//BUF_ADDSTR(txbuf, "Hello!\n\r");

/* Enable sending interrupt */
PIE1bits.TXIE = 1;

while (1) {
/* If the receiving buffer is not empty and there is enough
space in the sending buffer */


if (!BUF_EMPTY(rcbuf)&&BUF_GET(rcbuf) == 0x16) {
int index =-1;
checkSum = 0x00;
while(index++ < 16){
sData[index] = BUF_GET(rcbuf);
if(index>2 && index<14) checkSum ^= sData[index];
}
if (checkSum != sData[15]) return -1;
//PIE1bits.TXIE = 1;
}

if (BUF_LEN(txbuf) + 16 < BUF_SIZE) {
int index = -1;
checkSum = 0x00;
while(index++<16){
if(index==15) sData[index] = checkSum;
BUF_ADD(txbuf,sData[index];
if(index>2&&index<14) checkSum ^= sData[index]
}
PIE1bits.TXIE = 1;
}
/* Put the microcontroller in idle mode */
/* WARNING: If you want to debug the code with MPLAB Sim, you
need to remove the following two lines, since MPLAB Sim
cannot be waked up in idle mode by UART interrupt */
//OSCCONbits.IDLEN = 1;
//Sleep();
}
}

Hao Zhang

unread,
Oct 6, 2011, 10:15:39 PM10/6/11
to 3K04 project grp
this code is modified with ADC code. i only write within the while(1)
loop, the reset is predefined and ready to go. u guys can take a look
at it. if there is a problem, feel free to make your own modification
and post it with comment
Reply all
Reply to author
Forward
0 new messages