EmbeddedRelated.com
Code Snippets

ADXL345 Driver

May 29, 20131 comment Coded in C for the Microchip PIC16
#define ADXL_SDA  PIN_C4
#define ADXL_SCL  PIN_C3
#define ADXL_CS   PIN_C0

#use i2c(master, sda=ADXL_SDA, scl=ADXL_SCL)

void init_adxl345() 
{
   output_float(ADXL_SCL);
   output_float(ADXL_SDA);
   output_high(ADXL_CS);
}

BOOLEAN adxl345_ready() 
{
   int1 ack;
   i2c_start();            // If the write command is acknowledged,
   ack = i2c_write(0x3a);  // then the device is ready.
   i2c_stop();
   return !ack;
}

void write_adxl345(BYTE address, BYTE data) 
{
   while(!adxl345_ready());
   i2c_start();
   i2c_write(0x3a);
   i2c_write(address);
   i2c_write(data);
   i2c_stop();
}

BYTE read_adxl345(BYTE address) 
{
   BYTE data;

   while(!adxl345_ready());
   i2c_start();
   i2c_write(0x3a);
   i2c_write(address);
   i2c_start();
   i2c_write(0x3b);
   data=i2c_read(0);
   i2c_stop();
   return(data);
}

int16 read_adxl345_axis(BYTE address) 
{
   BYTE msb,lsb;

   while(!adxl345_ready());
   i2c_start();
   i2c_write(0x3a);
   i2c_write(address);
   i2c_start();
   i2c_write(0x3b);
   lsb=i2c_read(1);
   msb=i2c_read(0);
   i2c_stop();
   return((msb<<8)|lsb);
}

Software SPI

May 6, 20131 comment Coded in ASM for the Microchip PIC16
#include<p16f877a.inc>

#define	s_data_o	PORTC,5 ;serial data out
#define	s_data_i	PORTC,4	;serial data in
#define	s_clock		PORTC,3 ;clock out

	udata_shr
tx_reg	res	1
rx_reg	res	1

	code

;************************
;Configure I/O Ports
;Load data in WREG
;Call soft_spi_write
;************************
soft_spi_write
	global	soft_spi_write
	banksel	tx_reg
	movwf	tx_reg  	;store W = tx_reg
	banksel	PORTC 		;Bank 0
	bsf	STATUS,C 	;Set Carry Flag=1
send_next_bit
	rlf	tx_reg,F	;rotate left
	movf	tx_reg,F	;Check wheter 8 bit transmitted or not
	btfsc	STATUS,Z 	;If no ,send next bit
	return			;if yes,return

	bcf	s_data_o	;data line low
	btfsc	STATUS,C	;check the bit in carry,      	
	bsf	s_data_o	;if high,s_data_o =1
	fill	(nop),3
	bsf	s_clock		;s_clock=1	|		     _
	fill	(nop),5		;		|clock high to low _| |_		
	bcf	STATUS,C	;clear carry	|
	bcf	s_clock 	;S_clock=0  	|
	fill	(nop),3
	goto	send_next_bit	; looping process...........

;**************************************************
;Configure I/O Ports
;Call soft_spi_read	
;This fuction returns the received data is in WREG
;**************************************************
soft_spi_read			;subroutine for receive
	global	soft_spi_read
	movlw	0x01		;eight bit reception
	movwf	rx_reg
read_next_bit
	rlf	rx_reg,f	;rotating the rx_reg register to store the received bit
	bsf	s_clock 
	fill	(nop),5
	btfsc	s_data_i
	bsf	rx_reg,0	;receiving the data
	bcf	s_clock 
	fill	(nop),3
	btfss	STATUS,C	;testing whether the reception is compleate or not
	goto	read_next_bit	;if not compleated do the process again
	movf	rx_reg,W	;restore data in WREG
	return

	end

Interfacing SM630

May 6, 2013 Coded in C for the Microchip PIC16
#define cmd_add_fingerprint	0x40
#define cmd_search_fingerprint 0x44
#define cmd_packet	0x10
#define data_packet	0x20
#define res_packet	0x30

#define res_rcv_correct 0x01
#define res_rcv_error	0x02
#define res_opr_success	0x31
#define res_finger_detected	0x32
#define res_timeout	0x33
#define res_process_fail 0x34
#define res_para_error	0x35
#define res_fingerprint_found 0x39
#define res_fingerprint_unfound 0x3A

#use rs232(baud=57600,xmit=PIN_C6,rcv=PIN_C7,bits=8,parity=n,stop=1,stream=Finger,timeout=1000)//,force_sw)

int8 cmd_buffer[10],response_buffer[15];

int8 find_checksum(int8 total_byte)
{
	int8 byte_count;
	int16 check_sum=0;
	for(byte_count=0;byte_count<total_byte;byte_count++)
	{
		check_sum+=cmd_buffer[byte_count];
	}
	
	return(make8(check_sum,0));
}

void cmd_to_sm630(int8 total_byte)
{
	int8 byte_count;
	for(byte_count=0;byte_count<total_byte;byte_count++)
	{
		fputc(cmd_buffer[byte_count],Finger);
		delay_us(10);
	}		
}

void response_from_sm630(int8 total_byte)
{
	int8 byte_count;
	while(fgetc(Finger)!=0x4D);
	response_buffer[0]=0x4D;
	for(byte_count=1;byte_count<total_byte;byte_count++)
	{
		response_buffer[byte_count]=fgetc(Finger);
	}			
}		
	

int8 add_finger(int16 finger_id)
{
	cmd_buffer[0]=0x4D; //Packet Head
	cmd_buffer[1]=0x58; //Packet Head
	cmd_buffer[2]=cmd_packet; //Command Packet
	cmd_buffer[3]=0x03; //3 byte length
	cmd_buffer[4]=cmd_add_fingerprint; //Add finger Print cmd
	cmd_buffer[5]=make8(finger_id,1);//Higher byte of finger print id
	cmd_buffer[6]=make8(finger_id,0);//Lower byte of finger print id
	cmd_buffer[7]=find_checksum(7);//Check sum of 7 bytes
	
	cmd_to_sm630(8);
	response_from_sm630(6); //Read 6 bytes
	
	if(response_buffer[4] == res_rcv_correct)
	{
		
		response_from_sm630(7); //Read 6 bytes
		if(response_buffer[5] == res_opr_success)
		{
			//Display Press finger again
			//lcd_goto(2,1);
			//lcd_send_byte("  Press again   ");
			response_from_sm630(7); //Read 6 bytes
		}
	}
	return (response_buffer[5]);		
}	

int8 search_finger(int16& result_id,int16 num_fingerprint)
{
	output_low(PIN_A5);
	cmd_buffer[0]=0x4D; //Packet Head
	cmd_buffer[1]=0x58; //Packet Head
	cmd_buffer[2]=cmd_packet; //Command Packet
	cmd_buffer[3]=0x05; //5 byte length
	cmd_buffer[4]=cmd_search_fingerprint; //Search finger Print cmd
	cmd_buffer[5]=0x00; //Higher byte of Starting id
	cmd_buffer[6]=0x00; //Lower byte of Starting id
	cmd_buffer[7]=make8(num_fingerprint,1);//Higher byte of number of  fingerprints searched
	cmd_buffer[8]=make8(num_fingerprint,0);//Lower byte of number of  fingerprints searched
	cmd_buffer[9]=find_checksum(9);//Check sum of 9 bytes
	
	cmd_to_sm630(10);
	response_from_sm630(6); //Read 6 bytes
	if(response_buffer[4] == res_rcv_correct)
	{
		response_from_sm630(7); //Read 7 bytes
		if(response_buffer[5] == res_opr_success)
		{
				delay_ms(10);
				response_from_sm630(6); //Read 6 bytes
				//disp_response(6);
				if(response_buffer[5] == res_fingerprint_found)
				{
					response_buffer[0]=fgetc(Finger);
					response_buffer[1]=fgetc(Finger);
					result_id=make16(response_buffer[0],response_buffer[1]);
				}
		
	
		}

	}
	else
		response_buffer[5]=response_buffer[4];		
	return (response_buffer[5]);	
		

}

Interfacing SIM300

May 6, 2013 Coded in C for the Microchip PIC16
#use rs232(baud=19200,xmit=pin_C6,rcv=pin_C7,parity=n,bits=8,stop=1,stream=GSM,timeout=100)
 
int8 sms_buffer[40],ph_number[15]; 
 

 
void sync()
 {
	fprintf(GSM,"AT\n\r");
	delay_ms(100);
	fprintf(GSM,"AT\n\r");
	delay_ms(100);
	fprintf(GSM,"AT\n\r");
	delay_ms(100);
	fprintf(GSM,"AT\n\r");
	delay_ms(100);
}

void dial_modem()
{
	int8 i=0;
	fputc('A',GSM);
	fputc('T',GSM);
	fputc('D',GSM);
	fputc(' ',GSM);
	
	while(ph_number[i] !='\0' && i<16)
	{
		fputc(ph_number[i],GSM);
		i++;
	}
	fputc(';',GSM);
	fputc(0x0D,GSM);
	fputc(0x0A,GSM);
} 

void hang_call()
{
	fputc('A',GSM);
	fputc('T',GSM);
	fputc('H',GSM);
	fputc(0x0D,GSM);
	fputc(0x0A,GSM);
}
void set_text_mode()
{
	sync();
	fprintf(GSM,"AT+CMGF=1\n\r");
	
}
int1 get_sms(int8 intex_no)
{
	int8 count=0;
	set_text_mode();
	delay_ms(100);
	fprintf(GSM,"AT+CMGR=%u\n\r",intex_no);
	while(fgetc(GSM)!=0x0A);
	if(fgetc(GSM)=='+')
	{	
		
		while(fgetc(GSM)!='"');
		while(fgetc(GSM)!='"');
		while(fgetc(GSM)!='"');
		do
		{
			ph_number[count]=fgetc(GSM);
			count++;
		}while(ph_number[count-1] !='"' && count<15);
		ph_number[count-1]='\0';
		while(fgetc(GSM)!=0x0A);
		count=0;
		do
		{
			sms_buffer[count]=fgetc(GSM);
			count++;
		}while(sms_buffer[count-1] !=0x0D && count<24);
		sms_buffer[count-1]='\0';
		delay_ms(500);
		sync();	
		fprintf(GSM,"AT+CMGD=%u\n\r",intex_no);//delete sms
		
	}
	else
	{
		count=24;
	}	
	if(count>=24)
		return 0;
	else
	{
		return 1;	
	}	
		
}
void send_sms()
{
	int8 array_index;
	set_text_mode();
	delay_ms(100);
	fprintf(GSM,"AT+CMGS=");
	fputc('"',GSM);
	array_index=0;
	while(ph_number[array_index] !='\0')
	{
		fputc(ph_number[array_index],GSM);
		array_index++;
	}
	fputc('"',GSM);
	fputc(0x0D,GSM);
	fputc(0x0A,GSM);
	while(fgetc(GSM) !=' ');
	array_index=0;
	while(sms_buffer[array_index] !='\0')
	{
		fputc(sms_buffer[array_index],GSM);
		array_index++;
	}
	fputc(0x1A,GSM);// Ctrl-Z
	delay_ms(100);
}		

int8 read_strength()
{
	int8 rssi[3],rssi_byte;
	//output_low(PIN_A5);
	fprintf(GSM,"AT+CSQ\n\r");
	while(fgetc(GSM) !=' ');
	//output_high(PIN_A5);
	rssi[0]=fgetc(GSM) & 0x0F;
	rssi[1]=fgetc(GSM) & 0x0F;
	rssi_byte=rssi[0]*10;
	rssi_byte=rssi_byte+rssi[1];
	return rssi_byte;
}

Arithmetic Operations

April 15, 2013 Coded in ASM for the Microchip PIC16
UDATA
HIBYTE	RES	1	
LOBYTE	RES	1
COUNTX	RES	1
MULCND	RES	1
MULPLR	RES	1
BCD	RES	2
ACCaLO	res	1
ACCaHI	res	1
ACCbLO	res	1
ACCbHI	res	1
ACCcLO	res	1
ACCcHI	res	1
ACCdLO	res	1
ACCdHI	res	1
R2	res	1
R1	res	1
R0	res	1
TEMPX	res	1
L_temp	res	1
H_temp	res	1
w_save	res	1
RandHi	res	1
RandLo	res	1
parity	res	1

;*************************************************************************
; Multiplication MULPLR(8 bit) x MULCND(8 bit) -->HIBYTE(msb),LOBYTE(lsb)*  
; a) Load the multiplier in the location MULPLR				 *
; b) Load the multiplicant in the location MULCND			 *
; c) Call Mpy8x8						         * 
; d) Msb is in the location HIBYTE					 *
; e) Lsb is in the location LOBYTE					 *
;*************************************************************************
Mpy8x8	 	 	 
 	clrf	HIBYTE	 
 	clrf	LOBYTE	 
 	clrf	COUNTX	 
 	bsf	COUNTX, 3
		 
 	movf	MULCND, W	 
LoopX
	bcf	STATUS, C	 
 	btfsc	MULPLR, 0	 
 	addwf	HIBYTE, f	 
 	rrf	HIBYTE, f	 
 	rrf	LOBYTE, f	 
 	bcf	STATUS, C	 
 	rrf	MULPLR, f	 
 	decfsz	COUNTX, f	 
 	goto	LoopX	 
 	return	
;*******************************************************************
;Multiplication: ACCb(16 bits)*ACCa(16 bits) -> ACCb,ACCc (32 bits)*	
;(a) Load the 1st operand in location ACCaLO & ACCaHI (16 bits)	   *	
;(b) Load the 2nd operand in location ACCbLO & ACCbHI (16 bits)    *
;(c) CALL Mpy_16bit						   * 
;(d) The 32 bit result is in location (ACCbHI,ACCbLO,ACCcHI,ACCcLO)*
;*******************************************************************
Mpy_16bit
	movlw	.16 		; for 16 shifts
	movwf	temp
	movf	ACCbHI,W	; move ACCb to ACCd
	movwf	ACCdHI
	movf	ACCbLO,W
	movwf	ACCdLO
	clrf	ACCbHI
	clrf	ACCbLO
Mloop
	rrf	ACCdHI, F	 ;rotate d right
	rrf	ACCdLO, F
	btfsc	STATUS,C	 ;need to add?
	call	Add_16bit
	rrf	ACCbHI, F
	rrf	ACCbLO, F
	rrf	ACCcHI, F
	rrf	ACCcLO, F
	decfsz	temp, F 	;loop until all bits checked
	goto	Mloop
	return 	 

;******************************************************************
;This routine convert the hex value present in the WREG to decimal* 
;and store the results in the reg: BCD and BCD+1  		  *
;******************************************************************
BinBCD	 	 	 
 	clrf	BCD	 
	clrf	BCD+1
Again1
	addlw	0x9C	;subtract 100 and check for borrow
 	btfss	STATUS, C	 
 	goto	add100	 
 	incf	BCD+1, f
	goto	Again1
add100	 
	addlw	0x64
Again
	addlw	0xF6	;subtract 10 and check for borrow
 	btfss	STATUS, C	 
 	goto	SwapBCD	 
 	incf	BCD, f
	goto	Again
 	 	 	 
SwapBCD
	addlw	0x0A	 
 	swapf	BCD, f	 
 	iorwf	BCD, f	 
 	return	 	 

;***************************************************************
;This routine find the square of the number present in the WREG*
;The hex result is stored in WREG and the decimal result is    *  
;stored in GPRs BCD and BCD+1                                  * 
;***************************************************************
square
	movwf	COUNTX	 
	movlw	0x01
	movwf	TEMPX
	clrw
r_square	
	addwf	TEMPX,W
	incf	TEMPX,F
	incf	TEMPX,F
	decfsz	COUNTX,F
	goto	r_square
	movwf	w_save
	call	BinBCD	
	movf	w_save,W
	return
;*******************************************************************
;This routine find the square root of a number which is stored in  *
;WREG.The result is stored in WREG.If the number hasn't a finite   * 
;square root this function returns an error value EE in WREG       *
;*******************************************************************
square_root
	movwf	w_save
	movlw	0x01
	movwf	TEMPX
	movwf	COUNTX
loop
	movf	TEMPX,W
	subwf	w_save,f
	btfsc	STATUS,Z
	goto	zero
	btfss	STATUS,C
	goto	no_root
	incf	COUNTX,F
	incf	TEMPX,F
	incf	TEMPX,F
	goto	loop
zero
	movf	COUNTX,W
	return
no_root
	movlw	0XEE
	return
	
;********************************************************************
; Binary To BCD Conversion Routine				    *
; This routine converts a 16 Bit binary Number to a 5 Digit	    *
; BCD Number.							    *
; The 16 bit binary number is input in locations ACCaHI and         *
; ACCaLO with the high byte in ACCaHI.				    *
; The 5 digit BCD number is returned in R0, R1 and R2 with R0	    *
; containing the MSD in its right most nibble.			    *
;********************************************************************
Hex_to_Dec	 	 	 
 	bcf	STATUS, C	 
 	clrf	COUNTX	 
 	bsf	COUNTX, 4	;set count to 16
 	clrf	R0	 
 	clrf	R1	 
 	clrf	R2	 
Loop16a
	rlf	ACCaLO, f	 
 	rlf	ACCaHI, f	 
 	rlf	R2, f	 
 	rlf	R1, f	 
 	rlf	R0, f	 
 	decfsz	COUNTX, f	 
 	goto	Adjdec	 
 	return	 	 
Adjdec
	movlw	R2	;load as indirect address pointer
 	movwf	FSR	 
 	call	AdjBCD	 
  	incf	FSR, f	 
 	call	AdjBCD	 
 	incf	FSR, f	 
 	call	AdjBCD	 
 	goto	Loop16a	 
 	 	 	 
AdjBCD
	movf	INDF, w	 
 	addlw	0x03	 
 	movwf	TEMPX	 
 	btfsc	TEMPX,3;test if result > 7
 	movwf	INDF	 
 	movf	INDF, w	 
 	addlw	0x30	 
 	movwf	TEMPX	 
 	btfsc	TEMPX, 7	;test if result > 7
 	movwf	INDF	;save as MSD
 	return	 	 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Division : ACCb(16 bits) / ACCa(16 bits) -> ACCd(16 bits) with  ;
; Remainder in ACCc (16 bits)					  ;
; (a) Load the Denominator in location ACCaHI & ACCaLO ( 16 bits );
; (b) Load the Numerator in location ACCbHI & ACCbLO ( 16 bits )  ;
; (c) CALL Division						  ;
; (d) The 16 bit result is in location ACCdHI & ACCdLO		  ;
; (e) The 16 bit Remainder is in locations ACCcHI & ACCcLO	  ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Division
	clrf	COUNTX
	bsf	COUNTX,4 ; set count = 16
	clrf	ACCcHI
	clrf	ACCcLO
	clrf	ACCdLO
	clrf	ACCdHI
divLoop
	bcf	STATUS,C
	rlf	ACCbLO,F
	rlf	ACCbHI,F
	rlf	ACCcLO,F
	rlf	ACCcHI,F
	movf	ACCaHI,W
	subwf	ACCcHI,W ; check if a>c
	btfss	STATUS,Z
	goto	notz
	movf	ACCaLO,W
	subwf	ACCcLO,W ; if msb equal then check lsb
notz
	btfss	STATUS,C ; carry set if c>a
	goto	nosub	 ; if c < a
subca
	movf	ACCaLO,W ; c-a into c
	subwf	ACCcLO, F
	movf	ACCaHI,W
	subwf	ACCcHI, F
	bsf	STATUS,C ; shift a 1 into d (result)
nosub
	rlf	ACCdLO,F
	rlf	ACCdHI,F
	decfsz	COUNTX,F
	goto	divLoop
	
	return
;*******************************************************************
; Random Number Generator					   *
; This routine generates a 16 Bit Pseudo Sequence Random Generator *
; It is based on Linear shift register feedback. The sequence	   *
; is generated by (Q15 xorwf Q14 xorwf Q12 xorwf Q3 )		   *
; The 16 bit random number is in location RandHi(high byte)	   *
; & RandLo (low byte)						   *
; Before calling this routine, make sure the initial values	   *
; of RandHi & RandLo are NOT ZERO				   *
; A good chiose of initial random number is 0x3045		   *
;*******************************************************************
Random16
	rlf	RandHi,W
	xorwf	RandHi,W
	movwf	w_save
	rlf	w_save, F ; carry bit = xorwf(Q15,14)
	swapf	RandHi, F
	swapf	RandLo,W
	movwf	w_save
	rlf	w_save, F 
	xorwf	RandHi,W ; LSB = xorwf(Q12,Q3)
	swapf	RandHi, F
	andlw	0x01
	rlf	RandLo, F
	xorwf	RandLo, F
	rlf	RandHi, F
	return

;**********************************************************************
; BCD To Binary Conversion					      *   
; This routine converts a 5 digit BCD number to a 16 bit binary	      *
; number.							      *  
; The input 5 digit BCD numbers are asumed to be in locations	      *
; R0, R1 & R2 with R0 containing the MSD in its right most nibble.    *
; The 16 bit binary number is output in registers ACCaHI & ACCaLO     *
; ( high byte & low byte repectively ).				      *
; The method used for conversion is :				      *	
; input number X = abcde ( the 5 digit BCD number )		      *
; X = abcde = 10[10[10[10a+b]+c]+d]+e				      *	
;**********************************************************************
Dec_to_Hex
	clrf	ACCaHI
	movf	R0,W
	andlw	0x0F
	movwf	ACCaLO
	call	mpy10a ; result = 10a+b
	swapf	R1,W
	call	mpy10b ; result = 10[10a+b]
	movf	R1,W
	call	mpy10b ; result = 10[10[10a+b]+c]
	swapf	R2,W
	call	mpy10b ; result = 10[10[10[10a+b]+c]+d]
	movf	R2,W
	andlw	0x0F
	addwf	ACCaLO, F
	btfsc	STATUS,C
	incf	ACCaHI, F ; result = 10[10[10[10a+b]+c]+d]+e
	return		 ; BCD to binary conversion done

mpy10b
	andlw	0x0F
	addwf	ACCaLO, F
	btfsc	STATUS,C
	incf	ACCaHI, F
mpy10a
	bcf	STATUS,C ; multiply by 2
	rlf	ACCaLO,W
	movwf	L_temp
	rlf	ACCaHI,W ; (H_temp,L_temp) = 2*N
	movwf	H_temp
	bcf	STATUS,C ; multiply by 2
	rlf	ACCaLO, F
	rlf	ACCaHI, F
	bcf	STATUS,C ; multiply by 2
	rlf	ACCaLO, F
	rlf	ACCaHI, F
	bcf	STATUS,C ; multiply by 2
	rlf	ACCaLO, F
	rlf	ACCaHI, F ; (H_byte,L_byte) = 8*N
	movf	L_temp,W
	addwf	ACCaLO, F
	btfsc	STATUS,C
	incf	ACCaHI, F
	movf	H_temp,W
	addwf	ACCaHI, F
	return		 ; (H_byte,L_byte) = 10*N
;*********************************************************************************************
;This routine is used to find the parity bit(ODD or EVEN)an 8 bit no:stored in the WREG.     *
;The parity bit is stored in the LSB of parity reg.To find EVEN parity make the EVEN_PARITY  *
;definition TRUE.To find ODD parity make the EVEN_PARITY definition FALSE.  		     *	
;*********************************************************************************************
find_parity
	movwf	TEMPX
	swapf	TEMPX,W
	xorwf	TEMPX,W
	movwf	parity
	rrf	parity, F
	rrf	parity, F
	xorwf	parity,W
	andlw	0x03
	addlw	0x01
	movwf	TEMPX
	rrf	TEMPX,F
	rrf	TEMPX,W
	movwf	parity
	#if	EVEN_PARITY
	xorlw	0x01
	movwf	parity
	#endif
	return

;************************************************************************
; Subtraction : ACCb(16 bits) - ACCa(16 bits) -> ACCb(16 bits)		*
; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits )	*
; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits )	*
; (c) CALL Sub_16bit							*
; (d) The result is in location ACCbLO & ACCbHI ( 16 bits )		*
;************************************************************************
Sub_16bit
	call	Neg_16bit
	call	Add_16bit
	return		

;************************************************************************	
; Addition : ACCb(16 bits) + ACCa(16 bits) -> ACCb(16 bits)		*		
; (a) Load the 1st operand in location ACCaLO & ACCaHI ( 16 bits )	*
; (b) Load the 2nd operand in location ACCbLO & ACCbHI ( 16 bits )	*
; (c) CALL Add_16bit							*
; (d) The result is in location ACCbLO & ACCbHI ( 16 bits )		*
;************************************************************************
Add_16bit
	movf	ACCaLO,W
	addwf	ACCbLO, F ; add lsb
	btfsc	STATUS,C ; add in carry
	incf	ACCbHI, F
	movf	ACCaHI,W
	addwf	ACCbHI, F ; add msb
	return 
;************************************************************************
; 2's Compliment: negate ACCa ( -ACCa -> ACCa )				*
; (a) Load the operand in location ACCaLO & ACCaHI ( 16 bits )		*
; (b) CALL Neg_16bit							*
; (c) The result is in location ACCaLO & ACCaHI ( 16 bits )		*
;************************************************************************
Neg_16bit
	comf	ACCaLO, F ; 
	incf	ACCaLO, F
	btfsc	STATUS,Z
	decf	ACCaHI, F
	comf	ACCaHI, F
	return

Interfacing MAX6952

April 15, 2013 Coded in C for the Microchip PIC16
#define max_sdi PIN_C5
#define max_sdo PIN_C4
#define max_clk PIN_C3
#define max_cs  PIN_C2

const int8 user_font[120]= {0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C,
                            0x77,0x6B,0x5D,0x6B,0X77,
                            0x1C,0x22,0x7F,0x22,0x1C};
                                                        

#define config_addr 0x04
#define font_addr   0x05
#define test_addr   0x07
#define plane01_addr     0x20
#define plane02_addr     0x21
#define plane03_addr     0x22
#define plane04_addr     0x23
#define plane11_addr     0x40
#define plane12_addr     0x41
#define plane13_addr     0x42
#define plane14_addr     0x43

int8 config_byte;

void write_to_6952(int8 cmd,int8 data)
{
    int8 i;
    int16 ser_data;
    ser_data=make16(cmd,data);
    //shift_right(&ser_data,2,0);
    output_low(max_clk);
    output_low(max_cs);
    for(i=1;i<=16;++i)
    {
        output_bit(max_sdi,shift_left(&ser_data,2,0));
        output_high(max_clk);
        delay_us(10); 
       // if(i<16)       
            output_low(max_clk);
        //delay_us(6); 
    }
    output_high(max_cs);
    output_low(max_clk);
}   

void write_user_font()
{
    int8 j;
    write_to_6952(font_addr,0x80);
    for(j=0;j<120;j++)
    {
        write_to_6952(font_addr,user_font[j]);
    }    
}    
/*******************************************************************
if state=1,normal operation
if state=0,shutdown
if wrt=1,write to 6952,otherwise update the config_byte register
*******************************************************************/
void shutdown(int1 state, int1 wrt)
{
    if(state)
        config_byte |= 0x01;
    else
        config_byte &= 0xFE;
    if(wrt)
        write_to_6952(config_addr,config_byte);
}
/*******************************************************************
if state=1,enable blinking
if state=0,disable blinking
if wrt=1,write to 6952,otherwise update the config_byte register
*******************************************************************/
void blink_enable(int1 state,int1 wrt )
{
    if(state)
       config_byte |= 8;
    else
       config_byte &= 0xF7;
    if( wrt )
        write_to_6952(config_addr,config_byte);
}

/*************************************************************************
if state=1,put the display in test mode
if state=0,normal mode
Does not affect plane data - original display is restored when set 0.
**************************************************************************/
void display_test(int1 state )
{
     if(state)
        write_to_6952(test_addr,1);
     else
        write_to_6952(test_addr,0);
}

Interfacing ADS7807

April 10, 2013 Coded in C for the Microchip PIC16
#define sclk  PIN_D3
#define sdata PIN_D4
#define rc   PIN_D5
#define busy  PIN_D6
#define cs    PIN_C5

void init_ads7807()
{
    output_low(sclk);
    output_high(rc);
    delay_us(2);
    output_high(cs);
}

int32 read_ads7807()
{
BYTE i;
int32 adc_result=0;

while(!input(busy));
output_low(rc);
delay_cycles(1);
output_low(cs);
delay_us(1);
output_high(cs);
delay_cycles(1);
output_high(rc);
while(!input(busy));
output_low(cs);
    for(i=1;i<=16;++i)
    {
        output_high(sclk);
        shift_left(&adc_result,4,input(sdata));
        output_low(sclk);
    }
output_high(cs);
adc_result*=7629;
return adc_result/10000;
}

PGA117 driver

April 9, 2013 Coded in C for the TI MSP430
#define READ 0x6A00
#define WRITE 0x2A00
#define NOP WRITE 0x0000
#define SDN_DIS 0xE100
#define SDN_EN 0xE1F1

#define GAIN_1		0
#define GAIN_2		1
#define GAIN_4		2
#define GAIN_8		3
#define GAIN_16		4
#define GAIN_32		5
#define GAIN_64		6
#define GAIN_128	7

#define CS BIT0
#define DI BIT1
#define DO BIT2

void write_pga(unsigned int value);
void set_ch_gain(unsigned int ch,unsigned int gain);
void config_spi();

void config_spi()
{
	P1DIR |= 0x01;                            // P1.0 output
	P3SEL |= 0x0C;                            // P3.2,3 USCI_B0 option select
	P3DIR |= 0x01;                            // P3.0 output direction
	UCB0CTL0 |= UCMSB + UCMST + UCSYNC;       // 3-pin, 8-bit SPI mstr, MSB 1st
	UCB0CTL1 |= UCSSEL_2;                     // SMCLK
	UCB0BR0 = 0x02;
	UCB0BR1 = 0;
	UCB0CTL1 &= ~UCSWRST;                     // **Initialize USCI state machine**
}

void write_spi(char data)
{
	UCB0TXBUF = data;                  // Byte to SPI TXBUF
	while (!(IFG2 & UCB0TXIFG));       // USCI_A0 TX buffer ready?
}

void write_pga(unsigned int value)
{
	P3OUT &= ~CS;
	write_spi(value>>8);
	write_spi(value);
	P3OUT |= CS;
}

void set_ch_gain(unsigned int ch,unsigned int gain)
{
	unsigned int command;
	command = gain<<4;
	command += ch;
	command +=WRITE;
	write_pga(command);

}

SR-87 GPS Module

April 2, 2013 Coded in C for the Microchip PIC16
#use rs232(baud=4800,xmit=PIN_C6,rcv=PIN_C7,bits=8,stop=1,parity=n,stream=GPS,force_sw)

#include<string.h>
#include<stdlib.h>
//char latitude[17],longitude[17],buffer[17];

// Read the lattitude and longitude
void get_position()
{
	int8 rx_count,rx_buffer;
	rx_count=0;
	strcpy(buffer,"GPRMC");
	do
	{
		rx_count=0;
		output_low(PIN_A5);
		while(fgetc(GPS) !='$');
		while((rx_buffer=fgetc(GPS))!=',')
		{
			latitude[rx_count]=rx_buffer;
			rx_count++;
		}
		latitude[rx_count]='\0';
	}while(strcmp(latitude,buffer));
//*****************************************************************
	while(getc(GPS)!=',');
	while(getc(GPS)!=',');
	rx_count=0;
	do
	{
		rx_buffer=fgetc(GPS);
		latitude[rx_count]=rx_buffer;
		rx_count++;
	}while(rx_buffer!=',');
	latitude[rx_count]=fgetc(GPS);
	rx_count++;
	latitude[rx_count]='\0';
	rx_buffer=fgetc(GPS);
	rx_count=0;
	do
	{
		rx_buffer=fgetc(GPS);
		longitude[rx_count]=rx_buffer;
		rx_count++;
	}while(rx_buffer!=',');
	longitude[rx_count]=fgetc(GPS);
	rx_count++;
	longitude[rx_count]='\0';

}	
//wait untill a valid data
void get_fix()
{
   int8 rx_count,rx_buffer;
   rx_count=0;
   strcpy(buffer,"GPRMC");
   do
   {
      do
      {
         rx_count=0;
         while(fgetc(GPS) !='$');
         while((rx_buffer=fgetc(GPS))!=',')
         {
            latitude[rx_count]=rx_buffer;
            rx_count++;
         }
         latitude[rx_count]='\0';
      }while(strcmp(latitude,buffer));
      
      while(fgetc(GPS) !=',');
      rx_buffer=fgetc(GPS);
   }while(rx_buffer !='A');   
   

}

Interface matrix Keypad

March 25, 2013 Coded in C for the Microchip PIC16
/Keypad connection: 

#define col0 PIN_B3
#define col1 PIN_B2
#define col2 PIN_B1
#define col3 PIN_B0
#define row0 PIN_B7
#define row1 PIN_B6
#define row2 PIN_B5
#define row3 PIN_B4

#define num_col 4

// Keypad layout:
char const KEYS[4][4] = {{1,2,3,13},
                         {4,5,6,14},
                         {7,8,9,15},
                         {11,10,12,16}};

void init_keypad()
{
	output_high(row0);
	output_high(row1);
	output_high(row2);
	output_high(row3);
	output_low(col0);
	output_low(col1);
	output_low(col2);
	output_low(col3);	
}

short int ALL_ROWS (void)
{
   if (input (row0) & input (row1) & input (row2) & input (row3))
      return (0);
   else
      return (1);
}

//Will return a key value if pressed or 0 if not 

int8 get_key()
{
int8 row,col=0;
	do	
	{
		switch (col)
		{
			case 0   :
				output_low(col0);
				output_high(col1);
				output_high(col2);
				output_high(col3);
				break;
			case 1   :
				output_high(col0);
				output_low(col1);
				output_high(col2);
				output_high(col3);
				break;
			case 2   : 
				output_high(col0);
				output_high(col1);
				output_low(col2);
				output_high(col3);
				break;
			case 3   : 
				output_high(col0);
				output_high(col1);
				output_high(col2);
				output_low(col3);
				break;                    
		}
		
		if(!input (row0))
			row=1;
		else if(!input (row1))
			row=2;
		else if(!input (row2))
			row=3;
		else if(!input (row3))
			row=4;
		else
			row=0;
		col++;
	}while(!row && col<num_col);	
	if(row)
        return KEYS[row-1][col-1];
    else
        return 0;		
}
//function waits until any key is pressed and released.
int8 get_key_released()
{
int8 _key_temp ;
    do
    {
        _key_temp=get_key();
    }while(!_key_temp);
    init_keypad();
    do
    {
        while(ALL_ROWS());
        delay_ms(50);
    }
    while(ALL_ROWS());
return _key_temp;
}