diff code_part1/OSTC_code_asm_part1/i2c_eeprom.asm @ 0:96a35aeda5f2

Initial setup
author heinrichsweikamp
date Tue, 12 Jan 2010 15:05:59 +0100
parents
children 73014f788032
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/code_part1/OSTC_code_asm_part1/i2c_eeprom.asm	Tue Jan 12 15:05:59 2010 +0100
@@ -0,0 +1,365 @@
+
+; OSTC - diving computer code
+; Copyright (C) 2008 HeinrichsWeikamp GbR
+;    This program is free software: you can redistribute it and/or modify
+;    it under the terms of the GNU General Public License as published by
+;    the Free Software Foundation, either version 3 of the License, or
+;    (at your option) any later version.
+;    This program is distributed in the hope that it will be useful,
+;    but WITHOUT ANY WARRANTY; without even the implied warranty of
+;    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;    GNU General Public License for more details.
+;    You should have received a copy of the GNU General Public License
+;    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+; provides routines for external EEPROM via I2C
+; written by: Matthias Heinrichs, info@heinrichsweikamp.com
+; written: 10/30/05
+; last updated: 08/21/06
+; known bugs:
+; ToDo: use 2nd 32KB from external EEPROM for something
+
+incf_eeprom_address	macro	ext_ee_temp1	; Will increase eeprom_address:2 with the 8Bit value "ext_ee_temp1" and takes
+	movlw	ext_ee_temp1					; care of bank switching at 0x8000
+	call 	incf_eeprom_address0
+	endm
+
+incf_eeprom_address0:
+	movwf		ext_ee_temp1
+incf_eeprom_address1:
+	movlw		d'1'				; increase address
+	addwf		eeprom_address+0,F
+	movlw		d'0'
+	addwfc		eeprom_address+1,F
+	btfss		eeprom_address+1,7		; at address 8000?
+	bra			incf_eeprom_address2	; No, continue
+	
+	; Yes, clear eeprom_address:2
+	clrf		eeprom_address+0		; Clear eeprom address
+	clrf		eeprom_address+1
+	
+incf_eeprom_address2:
+	decfsz		ext_ee_temp1,F			; All done?
+	bra			incf_eeprom_address1	; No, continue
+	return								; Done.
+
+decf_eeprom_address	macro	ext_ee_temp1	; Will decrease eeprom_address:2 with the 8Bit value "ext_ee_temp1" and takes
+	movlw	ext_ee_temp1					; care of bank switching at 0x8000
+	call 	decf_eeprom_address0
+	endm
+
+decf_eeprom_address0:
+	movwf		ext_ee_temp1
+decf_eeprom_address1:
+	movlw		d'1'					; decrease address
+	subwf		eeprom_address+0,F
+	movlw		d'0'
+	subwfb		eeprom_address+1,F		
+
+	btfss		eeprom_address+1,7		; at address 8000?
+	bra			decf_eeprom_address2	; No, continue
+	
+	movlw		b'01111111'					; yes, reset highbyte
+	movwf		eeprom_address+1
+	
+decf_eeprom_address2:
+	decfsz		ext_ee_temp1,F			; All done?
+	bra			decf_eeprom_address1	; No, continue
+	return								; Done.
+
+
+write_external_eeprom:				; data in WREG
+								; increase address eeprom_address+0:eeprom_address+1 after write
+								; with banking after 7FFF
+	rcall		I2CWRITE			; writes WREG into EEPROM@eeprom_address
+	movlw		d'1'				; increase address
+	addwf		eeprom_address+0,F
+	movlw		d'0'
+	addwfc		eeprom_address+1,F
+	bcf			eeprom_overflow		
+	btfss		eeprom_address+1,7		; at address 8000?
+	return								; no, return
+
+	clrf		eeprom_address+0		; Clear eeprom address
+	clrf		eeprom_address+1
+	bsf			eeprom_overflow			; and set overflow bit
+	return
+write_external_eeprom_block:			; Writes a block of 64Byte (one page in external EEPROM without stop condition
+	btfsc		eeprom_blockwrite		; Blockwrite continue?
+	rcall		I2CWRITE_BLOCK2
+	btfss		eeprom_blockwrite		; Blockwrite start?
+	rcall		I2CWRITE_BLOCK
+	bsf			eeprom_blockwrite		; After the start, do blockwriting for the next 63Bytes!
+	
+	movlw		d'0'				; increase address
+	incf		eeprom_address+0,F	
+	addwfc		eeprom_address+1,F
+	bcf			eeprom_overflow		
+	
+	btfss		eeprom_address+1,7	; at address 8000
+	return						; no, return
+	
+	clrf		eeprom_address+0		; Clear eeprom address
+	clrf		eeprom_address+1
+	bsf			eeprom_overflow		; and set overflow bit
+	return
+I2CWRITE_BLOCK:
+	movwf		ext_ee_temp1				; Data byte in WREG
+	bsf			SSPCON2,SEN			; Start condition
+	rcall		WaitMSSP
+	movlw		b'10100110'			; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF				; control byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		eeprom_address+1,SSPBUF	; High Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		eeprom_address+0,SSPBUF	; Low Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+I2CWRITE_BLOCK2:	
+	movff		ext_ee_temp1, SSPBUF		; Data Byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	return
+
+
+get_free_EEPROM_location:			; Searches 0xFD, 0xFD, 0xFE and sets Pointer to 0xFE
+	clrf		ext_ee_temp1		; low address counter
+	clrf		ext_ee_temp2		; high address counter
+	bcf			second_FD			; clear flags
+	bcf			first_FD
+get_free_EEPROM_location3:
+	bsf			SSPCON2, PEN		; Stop condition
+	rcall		WaitMSSP	
+	bsf			SSPCON2,SEN			; Start condition
+	rcall		WaitMSSP
+	movlw		b'10100110'			; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF				; control byte
+	rcall		WaitMSSP	
+	btfsc		SSPCON2,ACKSTAT
+	bra			get_free_EEPROM_location3	; EEPROM NOT acknowledged, retry!
+	
+	movff		ext_ee_temp2,SSPBUF		; High Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		ext_ee_temp1,SSPBUF		; Low Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	
+	bsf			SSPCON2,RSEN		; Start condition
+	rcall		WaitMSSP
+	movlw		b'10100111'			; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF			; control byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+
+get_free_EEPROM_location2:
+	bsf			SSPCON2, RCEN		; Enable recieve mode
+	rcall		WaitMSSP	
+	btfsc		first_FD
+	bra			test_2nd_FD
+	bsf			first_FD			; found first 0xFD?
+	movlw		0xFD
+	cpfseq		SSPBUF
+	bcf			first_FD			; No
+	bra			get_free_EEPROM_location2c
+
+test_2nd_FD:
+	btfsc		second_FD
+	bra			test_FE
+	bsf			second_FD			; found second 0xFD?
+	movlw		0xFD
+	cpfseq		SSPBUF
+	bra			get_free_EEPROM_location2b	;No, clear both flags
+	bra			get_free_EEPROM_location2c	
+test_FE:
+	movlw		0xFE				; found the final 0xFE?
+	cpfseq		SSPBUF
+	bra			get_free_EEPROM_location2b	;No, clear both flags
+	movff		ext_ee_temp1,eeprom_address+0	;Yes, copy ext_ee_temp1->eeprom_address+0 and 
+	movff		ext_ee_temp2,eeprom_address+1	;ext_ee_temp2->eeprom_address+1
+	bra			get_free_EEPROM_location4	; Done.
+
+get_free_EEPROM_location2b:
+	bcf			second_FD			; clear both flags!
+	bcf			first_FD
+get_free_EEPROM_location2c:
+	movlw		d'1'				; and increase search address
+	addwf		ext_ee_temp1,F
+	movlw		d'0'
+	addwfc		ext_ee_temp2,F
+	
+	btfsc		ext_ee_temp2,7			; 8000 reached?
+	bra			get_free_EEPROM_location3b	; yes
+	
+	bsf			SSPCON2, ACKEN		; no, send Ack
+	rcall		WaitMSSP				
+	bra			get_free_EEPROM_location2	; and continue search
+get_free_EEPROM_location3b:
+	clrf 		eeprom_address+0		; Not found in entire EEPROM, set to address 0
+	clrf 		eeprom_address+1
+get_free_EEPROM_location4:
+	bsf			SSPCON2, PEN		; Stop
+	rcall		WaitMSSP	
+	
+	bcf			second_FD			; clear flags
+	bcf			first_FD
+	return					; return
+	
+	
+I2CREAD:
+	bsf			SSPCON2, PEN	; Stop
+	rcall		WaitMSSP	
+	bsf			SSPCON2,SEN		; Start condition
+	rcall		WaitMSSP
+	movlw		b'10100110'		; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF			; control byte
+	rcall		WaitMSSP	
+	btfsc		SSPCON2,ACKSTAT
+	bra			I2CREAD			; EEPROM NOT acknowledged, retry!	
+	movff		eeprom_address+1,SSPBUF	; High Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		eeprom_address+0,SSPBUF	; Low Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	
+	bsf			SSPCON2,RSEN	; Start condition
+	rcall		WaitMSSP
+	movlw		b'10100111'		; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF			; control byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	
+	bsf			SSPCON2, RCEN	; Enable recieve mode
+	rcall		WaitMSSP	
+	movf		SSPBUF,W		; copy read byte into WREG
+	bsf			SSPCON2, PEN	; Stop
+	rcall		WaitMSSP	
+	return
+
+I2CREAD2:						; same as I2CREAD but with automatic address increase 
+	rcall		I2CREAD
+	movlw		d'1'
+	addwf		eeprom_address+0,F
+	movlw		d'0'
+	addwfc		eeprom_address+1,F
+	bcf			eeprom_overflow		
+	btfss		eeprom_address+1,7	; at 0x8000?
+	return		; no, return
+	
+	clrf		eeprom_address+0	; Yes, clear address
+	clrf		eeprom_address+1
+	bsf			eeprom_overflow		; and set overflow bit
+	return
+	
+I2CWRITE:
+	movwf		ext_ee_temp1				; Data byte
+	bsf			SSPCON2,SEN			; Start condition
+	rcall		WaitMSSP
+	movlw		b'10100110'			; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF			; control byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		eeprom_address+1,SSPBUF	; High Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		eeprom_address+0,SSPBUF	; Low Address byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		ext_ee_temp1, SSPBUF		; Data Byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	bsf			SSPCON2,PEN			; Stop condition
+	rcall		WaitMSSP	
+	WAITMS		d'6'				; Write delay
+	return
+
+I2C_WaitforACK:
+	btfsc		SSPCON2,ACKSTAT		; checks for ACK bit from slave
+	rcall		I2CFail
+	return
+	
+I2CFail:
+	ostc_debug	'M'		; Sends debug-information to screen if debugmode active
+	call		set_LEDy					
+	rcall		I2CReset			; I2C Reset
+	bcf			PIR1,SSPIF
+	clrf		i2c_temp
+	return	
+	
+WaitMSSP:
+	decfsz		i2c_temp,F		; check for timeout during I2C action
+	bra			WaitMSSP2
+	bra			I2CFail			; timeout occured
+WaitMSSP2:
+	btfss		PIR1,SSPIF
+	bra		WaitMSSP
+	clrf		i2c_temp
+	bcf			PIR1,SSPIF
+	return
+
+I2CReset:						; Something went wrong (Slave holds SDA low?)
+	clrf		SSPCON1			; wake-up slave and reset entire module
+	ostc_debug	'N'		; Sends debug-information to screen if debugmode active
+	clrf		SSPCON2
+	clrf		SSPSTAT
+	bcf			TRISC,3			; SCL	OUTPUT
+	bsf			TRISC,4			; SDA	Input
+	bcf			PORTC,3
+	movlw		d'9'
+	movwf		i2c_temp		; clock-out 9 clock cycles manually
+I2CReset_1:
+	bsf			PORTC,3			; SCL=1
+	nop
+	btfsc		PORTC,4			; SDA=1?
+	bra		I2CReset_2		; =1, SDA has been released from slave
+	bcf			PORTC,3			; SCL=0	
+	bcf			PORTC,3
+	decfsz		i2c_temp,F
+	bra		I2CReset_1			; check for nine clock cycles
+I2CReset_2:
+	bsf			TRISC,3			; SCL	Input
+	clrf		SSPCON1			; set I²C Mode
+	WAITMS		d'10'				; Reset-Timeout for I2C devices
+	movlw		b'00000000'
+	movwf		SSPSTAT
+	movlw		b'00101000'
+	movwf		SSPCON1
+	movlw		b'00000000'
+	movwf		SSPCON2
+	movlw		d'8'				; 400kHz I2C clock @ 16MHz Fcy
+	movwf		SSPADD
+	call		clear_LEDy					
+	ostc_debug	'O'		; Sends debug-information to screen if debugmode active
+	return
+I2C_TX:
+	movwf		i2c_temp2				; Data byte
+	bsf			SSPCON2,SEN			; Start condition
+	rcall		WaitMSSP
+	movlw		b'10010000'		; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF			; control byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	movff		i2c_temp2, SSPBUF		; Data Byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	bsf			SSPCON2,PEN			; Stop condition
+	rcall		WaitMSSP	
+	return
+I2C_RX:
+	bcf			PIR1,SSPIF
+	bsf			SSPCON2,SEN			; Start condition
+	rcall		WaitMSSP
+	movlw		b'10010001'		; Bit0=0: WRITE, Bit0=1: READ
+	movwf		SSPBUF			; control byte
+	rcall		WaitMSSP	
+	rcall		I2C_WaitforACK
+	bsf			SSPCON2, RCEN	; Enable recieve mode
+	rcall		WaitMSSP	
+	movff		SSPBUF,i2c_temp2	; Data Byte
+	bsf			SSPCON2,ACKEN		; Master acknowlegde
+	rcall		WaitMSSP	
+	bsf			SSPCON2,PEN			; Stop condition
+	rcall		WaitMSSP	
+	return
\ No newline at end of file