please dont rip this site

Scenix I2CM_VP.SRC

; ******************************************************************************
;       Virtual Peripheral: I2C Subroutines
;
;       Length: 133 bytes (total)
;       Authors: Chip Gracey, President, Parallax Inc.
;		   modified by Craig Webb, Consultant to Scenix Semiconductor, Inc.
;       Written: 97/03/10 to 98/6/03
;
;******************************************************************************
;
;****** Assembler directives
;
; uses: SX28AC, 2 pages of program memory, 8 banks of RAM, high speed osc.
;       operating in turbo mode, with 8-level stack & extended option reg.
;                
		DEVICE  pins28,pages2,banks8,oschs
		DEVICE  turbo,stackx,optionx
		ID      'I2C'			;program ID label
		RESET   reset_entry             ;set reset/boot address
;
;******************************* Program Variables ***************************
;
; Port Assignment: Bit variables
;
scl             EQU     RA.0                    ;I2C clock
sda             EQU     RA.1                    ;I2C data I/O
;
;
;****** Register definitions (bank 0)
;
		org     8                       ;start of program registers
main            =       $                       ;main bank
;
temp            ds      1                       ;temporary storage
byte            ds      1                       ;temporary UART/I2C shift reg.
flags           DS      1                       ;program flags register
;
seq_flag        EQU     flags.1                 ;I2C: R/W mode (if sequential=1)
got_ack         EQU     flags.2                 ;     if we got ack signal
;
		org     90H                     ;bank4 variables
I2C             EQU     $                       ;I2C bank
;
data            DS      1                       ;data byte from/for R/W
address         DS      1                       ;byte address
count           DS      1                       ;bit count for R/W
delay           DS      1                       ;timing delay for write cycle
byte_count      DS      1                       ;number of bytes in R/W
num_bytes       DS      1                       ;number of byte to view at once
save_addr       DS      1                       ;backup location for address
;
in_bit          EQU     byte.0                  ;bit to receive on I2C
out_bit         EQU     byte.7                  ;bit to transmit on I2C 
;
control_r       =       10100001b               ;control byte: read E2PROM
control_w       =       10100000b               ;control byte: write E2PROM
portsetup_r     =       00000110b               ;Port A config: read bit
portsetup_w     =       00000100b               ;Port A config: write bit
eeprom_size     =       128                     ;storage space of EEPROM
;
t_all           =       31                      ;bit cycle delay (62=5 usec)
;
;
		ORG	0h			;Program Start adress
;
;******************************** I2C Subroutines *****************************
;
; These routines write/read data to/from the 24LCxx EEPROM at a rate of approx.
; 200kHz. For faster* reads (up to 400 kHz max), read, write, start amd stop
; bit cycles and time between each bus access must be individually tailored
; using the CALL Bus_delay:custom entry point with appropriate values in the W
; register - in turbo mode: delay[usec] = 1/xtal[MHz] * (6 + 4 * (W-1)).
; Acknowledge polling is used to reduce delays between successive operations 
; where the first of the two is a write operation. In this case, the speed
; is limited by the EEPROM's storage time.
;
;****** Subroutine(s) : Write to I2C EEPROM
; These routines write a byte to the 24LCxxB EEPROM. Before calling this
; subroutine, the address and data registers should be loaded accordingly. The
; sequential mode flag should be clear for normal byte writing operation.
; To write in sequential/page mode, please see application note. 
;
;       Input variable(s) : data, address, seq_flag
;       Output variable(s) : none
;       Variable(s) affected : byte, temp, count, delay
;       Flag(s) affected : none
;       Timing (turbo) : approx. 200 Kbps write rate
;                      : approx. 10 msec between successive writes
;
I2C_write       CALL    Set_address             ;write address to slave
:page_mode      MOV     W,data                  ;get byte to be sent
		CALL    Write_byte              ;Send data byte
		JB      seq_flag,:done          ;is this a page write?
		CALL    Send_stop               ;no, signal stop condition
:done           RETP                            ;leave and fix page bits
;
Set_address     CALL    Send_start              ;send start bit
		MOV     W,#control_w            ;get write control byte
		CALL    Write_byte              ;Write it & use ack polling
		JNB     got_ack,Set_address     ; until EEPROM ready
		MOV     W,address               ;get EEPROM address pointer
		CALL    Write_byte              ; and send it
		RETP                            ;leave and fix page bits
;
Write_byte      MOV     byte,W                  ;store byte to send
		MOV     count,#8                ;set up to write 8 bits
:next_bit       CALL    Write_bit               ;write next bit
		RL      byte                    ;shift over to next bit
		DJNZ    count,:next_bit         ;whole byte written yet?
		CALL    Read_bit                ;yes, get acknowledge bit
		SETB    got_ack                 ;assume we got it
		SNB     in_bit                  ;did we get ack (low=yes)?
		CLRB    got_ack                 ;if not, flag it
;
; to use the LED as a 'no_ack' signal, the ':toggle_led' line in the interrupt
;  section must be commented out, and the next 3 instructions uncommented.
;               CLRB    led_pin                 ;default: LED off
;               SNB     in_bit                  ;did we get ack (low=yes)?
;               SETB    led_pin                 ; if not, flag it with LED
;
		RETP                            ;leave and fix page bits
;
Write_bit       MOVB    sda,out_bit             ;put tx bit on data line
		MOV     !ra,#portsetup_w        ;set Port A up to write
		JMP     :delay1                 ;100ns data setup delay
:delay1         JMP     :delay2                 ; (note: 250ns at low power)
:delay2         SETB    scl                     ;flip I2C clock to high
;               MOV     W,#t_high                       ;get write cycle timing*
		CALL    Bus_delay               ;do delay while bus settles
		CLRB    scl                     ;return I2C clock low
		MOV     !ra,#portsetup_r        ;set sda->input in case ack
;               MOV     W,#t_low                ;get clock=low cycle timing*
		CALL    Bus_delay               ;allow for clock=low cycle
		RETP                            ;leave and fix page bits
;
Send_start      SETB    sda                     ;pull data line high
		MOV     !ra,#portsetup_w        ;setup I2C to write bit
		JMP     :delay1                 ;100ns data setup delay
:delay1         JMP     :delay2                 ; (note: 250ns at low power)
:delay2         SETB    scl                     ;pull I2C clock high
;               MOV     W,#t_su_sta             ;get setup cycle timing*
		CALL    Bus_delay               ;allow start setup time
:new            CLRB    sda                     ;data line goes high->low
;               MOV     W,#t_hd_sta             ;get start hold cycle timing*
		CALL    Bus_delay               ;allow start hold time          
		CLRB    scl                     ;pull I2C clock low
;               MOV     W,#t_buf                ;get bus=free cycle timing*
		CALL    Bus_delay               ;pause before next function             
		RETP                            ;leave and fix page bits
;
Send_stop       CLRB    sda                     ;pull data line low
		MOV     !ra,#portsetup_w        ;setup I2C to write bit
		JMP     :delay1                 ;100ns data setup delay
:delay1         JMP     :delay2                 ; (note: 250ns at low power)
:delay2         SETB    scl                     ;pull I2C clock high
;               MOV     W,#t_su_sto             ;get setup cycle timing*
		CALL    Bus_delay               ;allow stop setup time
		SETB    sda                     ;data line goes low->high
;               MOV     W,#t_low                ;get stop cycle timing*
		CALL    Bus_delay               ;allow start/stop hold time             
		RETP                            ;leave and fix page bits
;
Bus_delay       MOV     W,#t_all                ;get timing for delay loop
:custom         MOV     temp,W                  ;save it
:loop           DJNZ    temp,:loop              ;do delay
		RETP                            ;leave and fix page bits
;
;****** Subroutine(s) : Read from I2C EEPROM
; These routines read a byte from a 24LCXXB E2PROM either from a new address
; (random access mode), from the current address in the EEPROM's internal
; address pointer (CALL Read_byte:current), or as a sequential read. In either
; the random access or current address mode, seq_flag should be clear. Please
; refer to the application note on how to access the sequential read mode.
;
;       Input variable(s) : address, seq_flag
;       Output variable(s) : data
;       Variable(s) affected : byte, temp, count, delay
;       Flag(s) affected : none
;       Timing (turbo) : reads at approx. 200Kbps 
;
I2C_read        CALL    Set_address             ;write address to slave
:current        CALL    Send_start              ;signal start of read
		MOV     W,#control_r            ; get read control byte
		CALL    Write_byte              ; and send it
:sequential     MOV     count,#8                ;set up for 8 bits
		CLR     byte                    ;zero result holder
:next_bit       RL      byte                    ;shift result for next bit
		CALL    Read_bit                ;get next bit
		DJNZ    count,:next_bit         ;got whole byte yet?
		MOV     data,byte               ;yes, store what was read
		SB      seq_flag                ;is this a sequential read?
:non_seq        JMP     Send_stop               ; no, signal stop & exit
		CLRB    out_bit                 ; yes, setup acknowledge bit
		CALL    Write_bit               ;   and send it
		RETP                            ;leave and fix page bits
;
Read_bit        CLRB    in_bit                  ;assume input bit low
		MOV     !ra,#portsetup_r        ;set Port A up to read
		SETB    scl                     ;flip I2C clock to high
;               MOV     W,#t_high               ;get read cycle timing*
		CALL    Bus_delay               ;Go do delay
		SNB     sda                     ;is data line high?
		SETB    in_bit                  ;yes, switch input bit high
		CLRB    scl                     ;return I2C clock low
;               MOV     W,#t_buf                ;get bus=free cycle timing*
		CALL    Bus_delay               ;Go do delay
		RETP                            ;leave and fix page bits
;
; *****	High level functions: Store byte & Erase
;
Store_W		BANK    I2C                     ;switch to EEPROM bank
		MOV     data,W                  ;save incoming value
		CALL    I2C_Write               ;store it in EEPROM
		INC     address                 ;move to next address
		INC     byte_count              ;adjust # bytes stored
		MOV     W,eeprom_size           ;get memory size
		MOV     W,address-W             ;are we past end?
		SNZ                             ;if not, skip ahead
		CLR     address                 ;if so, reset it
:done           RETP                            ;leave and fix page bits
;
Erase_Mem       CLR     address                 ;restore address pointer
		MOV     num_bytes,#eeprom_size  ;wipe whole mem
:wipeloop       CLR     data                    ;byte to wipe with=0
;               MOV     data,address            ;byte to wipe with=addr
		CALL    I2C_write               ;wipe EEPROM byte
		INC     address                 ;move to next address
		DJNZ    num_bytes,:wipeloop     ;Erased enough yet?
		CLR     byte_count              ;done, reset stored count
		CLR     save_addr               ;reset backup address
		RETP                            ;leave and fix page bits
;
;************************** End of I2C Subroutines ****************************
;
;***************************** MAIN PROGRAM CODE ******************************
;
;		ORG     100h
;
; Program execution begins here on power-up or after a reset
;
reset_entry
		mov      ra,#%1011              ;initialize port RA
		mov     !ra,#%0100              ;Set RA in/out directions
		CLR     FSR                     ;reset all ram starting at 08h
:zero_ram       SB      FSR.4                   ;are we on low half of bank?
		SETB    FSR.3                   ;If so, don't touch regs 0-7
		CLR     IND                     ;clear using indirect addressing
		IJNZ    FSR,:zero_ram           ;repeat until done

		mov     !option,#%11011111      ;disable rtcc interrupt
;
; Main Program Loop
;
:loop		MOV	W,#55			;example byte
		CALL    Store_W                 ;Store byte in next I2c address
;
; <program code goes here>
;
		JMP     :loop                   ;back to main loop
;
;***************
		END                             ;End of program code


file: /Techref/scenix/i2cm_vp.src, 13KB, , updated: 1999/2/20 12:23, local time: 2024/11/19 06:22,
TOP NEW HELP FIND: 
3.141.0.59:LOG IN

 ©2024 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE!

<A HREF="http://linistepper.com/Techref/scenix/i2cm_vp.src"> scenix i2cm_vp</A>

Did you find what you needed?