#include <p18f1320.h>
// XLCR pin is PORTA:4                // <- adjust this if needed

extern void start_I2C(void);
extern void stop_I2C(void);
extern void write_I2C(unsigned char c);
extern unsigned char read_I2C(unsigned char ack);
extern void delay(unsigned char d);

unsigned int c1, c2, c3, c4, c5, c6, c7, d1, d2;
unsigned char a, b, c, d;
int temp;
int press;
int t;
long tl;
char cnt;

unsigned char read_conf_register(unsigned char r)
{
  unsigned char v;
  start_I2C();
  write_I2C(0xA0);			// sensor address & write	
  write_I2C(r);				// send reg address	
  start_I2C();              // restart 
  write_I2C(0xA1);			// sensor address & read
  v = read_I2C(0);          // read byte & NACK
  stop_I2C();
  return v;
}

int read_int_conf_register(unsigned char r)
{
  unsigned char msb, lsb;
  start_I2C();
  write_I2C(0xA0);			// sensor address & write	
  write_I2C(r);				// send reg address
  start_I2C();              // restart 
  write_I2C(0xA1);			// sensor address & read
  msb = read_I2C(1);		// read MSB & ACK
  lsb = read_I2C(0);		// read LSB & NACK
  stop_I2C();
  return (((int)msb<<8) | ((int)lsb));
}

int read_int_register(void)
{
  unsigned char msb, lsb;
  start_I2C();
  write_I2C(0xEE);			// sensor address & write	
  write_I2C(0xFD);				// send reg address
  start_I2C();              // restart 
  write_I2C(0xEF);			// sensor address & read
  msb = read_I2C(1);		// read MSB & ACK
  lsb = read_I2C(0);		// read LSB & NACK
  stop_I2C();
  return (((int)msb<<8) | ((int)lsb));
}

void write_control_register(unsigned char v)
{
  start_I2C();
  write_I2C(0xEE);			// sensor address & write	
  write_I2C(0xFF);			// control reg address
  write_I2C(v);				// write data
  stop_I2C();		
}

void hp03sa_get_cal_data(void) 
{
  PORTA &= 0xEF;			// clear XCLR 
  c1 = read_int_conf_register(16);
  c2 = read_int_conf_register(18);
  c3 = read_int_conf_register(20);
  c4 = read_int_conf_register(22);
  c5 = read_int_conf_register(24);
  c6 = read_int_conf_register(26);
  c7 = read_int_conf_register(28);
  a =  read_conf_register(30);
  b =  read_conf_register(31);
  c =  read_conf_register(32);
  d =  read_conf_register(33);
}

void hp03sa_get_data(int* temp, int* press) 
{
  unsigned char ab;
  int dUT, off, sens; 

  PORTA |= 0x10;			// set XCLR 
  write_control_register(0xF0);  // read d1
  delay(40); 				     //longer than 40 ms
  d1 = read_int_register();

  write_control_register(0xE8);  // read d2
  delay(40);                     // longer than 40ms
  d2 = read_int_register();
  PORTA &= 0xEF;			// clear XCLR
 
  //calculate temperature
  t = d2 - c5;
  ab = (t >= 0) ? a : b;
  t -= (((((long)t*t) >> 14)*ab) >> c);
  dUT = t;

  tl = ((long)dUT*c6);
_asm 
	movff tl+3, tl+1				// tl = tl >> 16
	movff tl+2, tl					// signed shift!
	movlw 0x80
	addwf tl+1, 0, 1
	movlw 0
	btfsc STATUS, 0, 0
   	 movlw -1
  	movwf tl+2, 1
  	movwf tl+3, 1

  	movff d, cnt					// t = t >> d
L:  movlw 0x80						// signed shift!
  	addwf t+1, 0, 1
   	rrcf  t+1, 1, 1
  	rrcf  t, 1, 1
    decfsz cnt, 1, 1
      bra L
_endasm
  t = 250 + tl - t;
  *temp = t;

  // calculate offset, sensitivity, and pressure
  tl = (long)dUT * (int)(c4 - 1024);
_asm
 	movlw 12   
  	movwf cnt, 1					// tl = tl >> 12
L:  movlw 0x80						// signed shift!
  	addwf tl+3, 0, 1
   	rrcf  tl+3, 1, 1
  	rrcf  tl+2, 1, 1
	rrcf  tl+1, 1, 1
	rrcf  tl, 1, 1
    decfsz cnt, 1, 1
      bra L
_endasm

  off = (c2 << 2) + tl;
  tl = (long)dUT * c3;
_asm
 	movlw 10   
  	movwf cnt, 1					// tl = tl >> 10
L:  movlw 0x80						// signed shift!
  	addwf tl+3, 0, 1
   	rrcf  tl+3, 1, 1
  	rrcf  tl+2, 1, 1
	rrcf  tl+1, 1, 1
	rrcf  tl, 1, 1
    decfsz cnt, 1, 1
      bra L  
_endasm
  sens = c1 + tl;

  tl = sens;
  tl = (long)sens * (int)(d1 - 7168);
_asm
 	movlw 14   
  	movwf cnt, 1					// tl = tl >> 14
L:  movlw 0x80						// signed shift!
  	addwf tl+3, 0, 1
   	rrcf  tl+3, 1, 1
  	rrcf  tl+2, 1, 1
	rrcf  tl+1, 1, 1
	rrcf  tl, 1, 1
    decfsz cnt, 1, 1
      bra L  
_endasm
  t = tl - off;
  t = (t >> 2);
  t += (t >> 2) + c7;
  t = (((t + 5) / 10)*3) >> 2; // round off and convert to mmHg 
  *press = t;
}
