; ===================== I2Clib.asm ===================== ; ; I2C master ; ; $Id$: ; ; This is a collection of subroutines to implement I2C master in the TRAP chip ; ; ====================================================== ; #ifdef traceon ORG 0x100 #endif ; ****************************** ; READ ; input data: device address dev_addr ; start address start_addr ; number of reads nbytes ; output data: ; DBANK at read_buff ; registers changed: ; dev_addr, nbytes, i2data ; ibit, wrk, ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_sread: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mov 0, timeoutcnt ; clear the timeout counter ; write the internal address mov 0xFE, i2data and dev_addr, i2data, dev_addr ; clear read flag mvpcr +2, return2 jmp cc_uncond, i2c_start ; start mov dev_addr, i2data ; putbyte(device address) mvpcr +2, return2 jmp cc_uncond, i2c_putbyte mvpcr +2, return2 jmp cc_uncond, i2c_getack ; getack mov start_addr, i2data ; putbyte(start address) mvpcr +2, return2 jmp cc_uncond, i2c_putbyte mvpcr +2, return2 jmp cc_uncond, i2c_getack ; getack mvpcr +2, return2 jmp cc_uncond, i2c_start ; start or dev_addr, c1, dev_addr ; set read flag mov dev_addr, i2data ; putbyte(device address) mvpcr +2, return2 jmp cc_uncond, i2c_putbyte mvpcr +2, return2 jmp cc_uncond, i2c_getack ; getack iext read_buff mov read_buff, ioaddr ; read the bytes i2c_snbytes: mvpcr +2, return2 jmp cc_uncond, i2c_getbyte ; getbyte sgio+ i2data ; DATA(x)=BUFFER sub nbytes, c1, nbytes jmp cc_zero, i2c_exit_sread mvpcr +2, return2 jmp cc_uncond, i2c_giveack ; giveack jmp cc_uncond, i2c_snbytes i2c_exit_sread: mvpcr +2, return2 jmp cc_uncond, i2c_stop ; stop jmp cc_uncond, return1 ; end of rread #ifdef traceon ORG 0x200 #endif ; ****************************** ; WRITE ; input data: device address dev_addr ; start address start_addr ; number of bytes nbytes ; the data in DBANK at write_buff ; registers changed: ; dev_addr, nbytes, i2data ; ibit, wrk, ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_swrite: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mov 0, timeoutcnt ; clear the timeout counter iext write_buff mov write_buff, ioaddr mov 0xFE, i2data and dev_addr, i2data, dev_addr ; clear read flag mvpcr +2, return2 jmp cc_uncond, i2c_start ; start mov dev_addr, i2data ; putbyte(device address) mvpcr +2, return2 jmp cc_uncond, i2c_putbyte ;swrepa: mvpcr +2, return2 jmp cc_uncond, i2c_getack ; getack ; ; Note: here is better to define a second getack_long ; ; procedure which wait much more, in order of 100 ms, ; ; still not implemented and tested! ; ; added by P.Popov ; ; if the latest programming cycle in EEPROM is not finished ; mov c9 wrk ; or wrk wrk wrk ; check if c9=0 = the last getack was successfull ; jmp cc_zero ack_is ; and exit ; ; clear the timeout counter ; mov c0 wrk ; ; sgio wrk 0xC01 ; c9=0 ; jmpr cc_busy 0 ; jmp cc_uncond swrepa ;ack_is: mov start_addr, i2data ; putbyte(start address) mvpcr +2, return2 jmp cc_uncond, i2c_putbyte mvpcr +2, return2 jmp cc_uncond, i2c_getack ; getack ; write the bytes i2c_wnbytes: lgio+ 0 jmpr cc_busy, 0 lpio 0x300, i2data mvpcr +2, return2 jmp cc_uncond, i2c_putbyte ; putbyte(data) mvpcr +2, return2 jmp cc_uncond, i2c_getack ; getack sub nbytes, c1, nbytes jmp cc_nzero, i2c_wnbytes mvpcr +2, return2 jmp cc_uncond, i2c_stop ; stop jmp cc_uncond, return1 ; end of rwrite #ifdef traceon ORG 0x300 #endif ; ****************************** ; INIT ; registers changed: ; wrk, ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_init: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mov msk_ssda, wrk mov msk_sscl, wrk1cs or wrk, wrk1cs, wrk jmpr cc_busy, 0 iext SEBDOU sgio wrk, SEBDOU ; SDA and SCL 1 jmpr cc_busy, 0 iext SEBDEN sgio wrk, SEBDEN ; SDA and SCL enabled mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 mvpcr +2, return3 jmp cc_uncond, i2c_clrsck ; sck=0 mvpcr +2, return2 jmp cc_uncond, i2c_stop ; stop mvpcr +2, return2 jmp cc_uncond, i2c_stop ; stop mvpcr +2, return2 jmp cc_uncond, i2c_stop ; stop mvpcr +2, return2 jmp cc_uncond, i2c_stop ; stop #ifdef traceon mov ramaddr, deb_reg iext 0xDEAD mov 0xDEAD, wrk #ifdef notsim win: sra+ wrk cmp ramaddr, 0xFF0 jmp cc_ltu, win #endif mov deb_reg, ramaddr #endif jmp cc_uncond, return1 ; end of i2c_init #ifdef traceon ORG 0x320 #endif ; ****************************** ; START ; registers changed: ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_start: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mvpcr +2, return3 jmp cc_uncond, i2c_setsck ; sck=1 mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 mvpcr +2, return3 jmp cc_uncond, i2c_clrsda ; sda=0 mvpcr +2, return3 jmp cc_uncond, i2c_clrsck ; sck=0 mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 jmp cc_uncond, return2 ; end of start #ifdef traceon ORG 0x340 #endif ; ****************************** ; STOP ; registers changed: ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_stop: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mvpcr +2, return3 jmp cc_uncond, i2c_clrsda ; sda=0 mvpcr +2, return3 jmp cc_uncond, i2c_setsck ; sck=1 mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 jmp cc_uncond, return2 ; end of stop #ifdef traceon ORG 0x360 #endif ; ****************************** ; PUTBYTE ; input data: ; i2data is the byte to be send ; registers changed: ; ibit, wrk, ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_putbyte: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mov i2data, wrk mov 7, ibit i2c_pbit: shlt -8, wrk mvpcr +3, return3 jmp cc_ncarry, i2c_clrsda jmp cc_uncond, i2c_setsda ; SDA= bit(r4) of i2data mvpcr +2, return3 jmp cc_uncond, i2c_setsck ; sck=1 mvpcr +2, return3 jmp cc_uncond, i2c_clrsck ; sck=0 shl 1, wrk, wrk ; wrk << 1 sub ibit, c1, ibit jmp cc_ncarry, i2c_pbit mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 jmp cc_uncond, return2 ; end of putbyte #ifdef traceon ORG 0x380 #endif ; ****************************** ; GETBYTE ; i2data is the result byte ; changed wrk, ibit ; wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_getbyte: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mov 7, wrk mov 0, i2data i2c_gbit: mvpcr +2, return3 jmp cc_uncond, i2c_setsck ; sck=1 mvpcr +2, return3 jmp cc_uncond, i2c_getsda ; ibit=sda shl 1, i2data, i2data or i2data, ibit, i2data mvpcr +2, return3 jmp cc_uncond, i2c_clrsck ; sck=0 sub wrk, c1, wrk jmp cc_ncarry, i2c_gbit mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 jmp cc_uncond, return2 ; end of getbyte #ifdef traceon ORG 0x3A0 #endif ; ****************************** ; GIVEACK ; registers changed: wrk1cs, wrk2cs (in set/clr sda/scl) ; ****************************** i2c_giveack: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mvpcr +2, return3 jmp cc_uncond, i2c_clrsda ; sda=0 mvpcr +2, return3 jmp cc_uncond, i2c_setsck ; sck=1 mvpcr +2, return3 jmp cc_uncond, i2c_clrsck ; sck=0 mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 jmp cc_uncond, return2 ; end of giveack #ifdef traceon ORG 0x3C0 #endif ; ****************************** ; GETACK ; registers changed wrk, ibit ; wrk1cs, wrk2cs (in set/clr sda/scl) ; in case of timeout timeoutcnt will be incremented ; ****************************** i2c_getack: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif mvpcr +2, return3 jmp cc_uncond, i2c_setsda ; sda=1 mvpcr +2, return3 jmp cc_uncond, i2c_setsck ; sck=1 iext timeout mov timeout, wrk i2c_gsda: mvpcr +2, return3 jmp cc_uncond, i2c_getsda ; ibit=sda sub wrk, c1, wrk jmp cc_zero, i2c_tout or ibit, ibit, ibit jmp cc_nzero, i2c_gsda i2c_exit_getack: mvpcr +2, return3 jmp cc_uncond, i2c_clrsck ; sck=0 jmp cc_uncond, return2 i2c_tout: add timeoutcnt, c1, timeoutcnt jmp cc_uncond, i2c_exit_getack ; end of getack #ifdef traceon ORG 0x400 #endif ; ****************************** ; SDA = 0 ; registers changed: wrk1cs, wrk2cs ; ****************************** i2c_clrsda: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif iext sebdou lgio 0, sebdou jmpr cc_busy, 0 lpio 0x300, wrk1cs mov msk_csda, wrk2cs and wrk2cs, wrk1cs, wrk1cs iext sebdou sgio wrk1cs, sebdou jmp cc_uncond, i2c_delay ; end of clrsda #ifdef traceon ORG 0x420 #endif ; ****************************** ; SDA = 1 ; registers changed: wrk1cs, wrk2cs ; ****************************** i2c_setsda: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif iext sebdou lgio 0, sebdou jmpr cc_busy, 0 lpio 0x300, wrk1cs mov msk_ssda, wrk2cs or wrk2cs, wrk1cs, wrk1cs iext sebdou sgio wrk1cs, sebdou jmp cc_uncond, i2c_delay ; end of setsda: #ifdef traceon ORG 0x440 #endif ; ****************************** ; READ SDA ; the result is in ibit ; registers changed: wrk1cs (in delay) ; ****************************** i2c_getsda: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif iext sebdin lgio 0, sebdin jmpr cc_busy, 0 lpio 0x300, ibit shl pos_sdai, ibit, ibit and ibit, c1, ibit jmp cc_uncond, i2c_delay ; end of getsda #ifdef traceon ORG 0x500 #endif ; ****************************** ; SCL = 1 ; registers changed: wrk1cs, wrk2cs ; ****************************** i2c_setsck: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif iext sebdou lgio 0, sebdou jmpr cc_busy, 0 lpio 0x300, wrk1cs mov msk_sscl, wrk2cs or wrk2cs, wrk1cs, wrk1cs iext sebdou sgio wrk1cs, sebdou jmp cc_uncond, i2c_delay ; end of setsck: #ifdef traceon ORG 0x520 #endif ; ****************************** ; SCL = 0 ; registers changed: wrk1cs, wrk2cs ; ****************************** i2c_clrsck: #ifdef traceon mvpcr 0, deb_reg sra+ deb_reg #endif iext sebdou lgio 0, sebdou jmpr cc_busy, 0 lpio 0x300, wrk1cs mov msk_cscl, wrk2cs and wrk2cs, wrk1cs, wrk1cs iext sebdou sgio wrk1cs, sebdou jmp cc_uncond, i2c_delay ; end of clrsck: #ifdef traceon ORG 0x600 #endif ; ****************************** ; DELAY timedelay*3 ; registers changed: wrk1cs ; ****************************** i2c_delay: mov timedelay, wrk1cs i2c_ldel: sub wrk1cs, c1, wrk1cs jmp cc_nzero, i2c_ldel jmp cc_uncond, return3 nop ; END OF ALL SUBROUTINES