***************************************                                    **           Transgalactic            **             Instruments            **                                    ***************************************** power nukeman mcu - i2c access (master mode only) routines* two port c pins are used; portc must be in open collector* mode. Scl and sda bits in the output port are constantly* zeroes; ddrc controls the output state (off=1 and readable,* on=0 and not readable - but known to be 0).**CR     EQU    $0DLF     EQU    $0AEOT    EQU    $04SPACE  EQU    $20**         opt       nolist         use       hc11         use       nmq         opt       list***         xref      pstat2         xref      inbytx,derr,out2hx,xcdok,xout2h** newly introduced bsct variables come here so old retain* their addresses (some other of the new ones are in nmio.sa to* replace the former local kbd vars)*         sect      1* newly introduced bsct variables:p3val: do.b        1         3.3V valuep3sta:   do.b      1         3.3V statusaminute: do.b      1         alarm minuteahour:   do.b      1         alarm houraday:    do.b      1         alarm dayamonth:  do.b      1         alarm month (Jan is 1; 0 =no alarm set)ayear:   do.b      1         alarm year** i2c related follow:i2caddr: do.b      1         i2c address to output for transferi2cbcnt: do.b      1         i2c transfer byte count (decremented during tfr)***         sect      2      left in bsct, only half full anywayi2cbuff: do.b      8         up to 8 bytes at a transferi2cbln:  equ       *-i2cbuff**       sect        3** reserve i2c inerface*rsvi2c:         sei                 multi-task access to this         brset     pstat2,p2.i2c,busy2c          if busy         bset      pstat2,p2.i2c                 reserve i2c         cli                 unmask immediately         clc         rtsbusy2c         cli                 unmask         ldab      #e$busy   'busy' error         sec                 indiicate error         rts                 *return*          ** release i2c interface*rlsi2c:         bclr      pstat2,p2.i2c       release i2c         rts                           *return*waii2c*         swi                 exit task, then try again         dex                 count down - long enough         beq       busy2c    if failed 65536 times, return busy error         bra       tryag2c** read/write i2c data command* input: i2c address (bit 0 is r/w bit),*        no. of bytes,*        data if r/w bit was 0  (no third byte of read)*i2crw:         ldx       #0        some limittryag2c         bsr       rsvi2c    reserve i2c interface         bcs       waii2c    wait for it to get free         jsr       inbytx    input address (aborts & returns on no hex)         staa      i2caddr   prepare address         tab                 keep in b as well         jsr       inbytx    no. of bytes         staa      i2cbcnt   initialize byte count         beq       lnovfl    0 would mean 256 bytes - too many         lsrb                write requested?         bcs       readi2c   branch not         cmpa      #i2cbln   too many?         bhi       lnovfl    branch yes, length exceeded error* input bytes         ldab      i2cbcnt   recall count         ldx       #i2cbuff         set       loop,*         jsr       inbytx    read a data byte         staa      0,x       write to buffer         inx                 move pointer         decb                counter down         bne       loop      input all bytes*         bsr       wri2c     write to i2c         bcs       erri2c    if error         bsr       rlsi2c    release i2c         jmp       xcdok     echo a O and returnlnovfl         ldab      #e$ovfl   overflow errorerri2c         bsr       rlsi2c    release i2c         jmp       derr      send error & return*readi2c         ldaa      i2cbcnt   take byte count         psha                save on stack         jsr       rdi2c     read from i2c         pula                recall byte count         bcs       erri2c    if error reading         bsr       rlsi2c    release i2c* output read values         ldx       #i2cbuff  point to buffer         set       loop,*         jsr       xout2h    send as hex         inx         deca                count down         bne       loop      send all         clc                 make sure no carry         rts                 *return*** write a number of bytes from (y)+ at b i2c address*i2cwry:         stab      i2caddr             setup i2c address         staa      i2cbcnt             and byte count         bra       i2cwrcm** write a to address b*i2cwr:         stab      i2caddr             setup address         staa      /i2cbuff             prepare buffer         ldaa      #1                  just 1 byte         staa      i2cbcnt             setup byte count* fall into wri2c         ** write to device**wri2c:         ldy       #i2cbuff  point to bufferi2cwrcm         ldx       #regs     point to registers         bclr      ddrc,x,c.scl+c.sda  make sure both are set         brset     portc,x,c.scl+c.sda,goti2c1   if seen high         bra       bsyi2c  if busygoti2c1         ldab      i2caddr             take address         bsr       sendaddr            send the address first         bcs       retcwr              if error sending address* send datawbloop         ldaa      0,y       pickup a byte         ldab      #7        counter*         set       loop,*         bset      ddrc,x,c.scl       clock low         asla                          test the bit         bcc       odt0                if 0         bclr      ddrc,x,c.sda       else set to 1         bclr      ddrc,x,c.scl       clock high as well         decb                count down         bpl       loop         bra       didodt              when all sentodt0         bset      ddrc,x,c.sda       else set to 1         bclr      ddrc,x,c.scl       clock high as well         decb                count down         bpl       loopdidodt   *         bset      ddrc,x,c.scl       clock low once again         bclr      ddrc,x,c.sda       data high         bclr      ddrc,x,c.scl       clock high again         brset     portc,x,c.scl,gotnoa1   wait clock to be left high         brset     portc,x,c.scl,gotnoa1   wait clock to be left high         brset     portc,x,c.scl,gotnoa1   wait clock to be left high         brset     portc,x,c.scl,gotnoa1   wait clock to be left highbsywr2         bra       bsyi2c                  if clock stays lowgotnoa1* abort if not an acknowledge         iny                           point to next buffer address         brset     portc,x,c.sda,trmwic  if no ack, terminate         dec       i2cbcnt             count down bytes         bne       wbloop              write all bytestrmwic*         bset      ddrc,x,c.scl       clock low again         bset      ddrc,x,c.sda       data low as well         bclr      ddrc,x,c.scl       release clock line         brset     portc,x,c.scl,snxstp         brset     portc,x,c.scl,snxstp         brset     portc,x,c.scl,snxstp         brset     portc,x,c.scl,snxstp         bra       bsywr2              if error* send stop snxstp*         bclr      ddrc,x,c.sda       release sda line - clock high, stop         clc                 no errorretcwr         rts*bsyi2c         ldab      #e$busy   indicate busy         sec         rts                 *return*** send address in b to the i2c wire*sendaddr         psha                          save a         bset      ddrc,x,c.sda       sda low         ldaa      #7                  counter         set       loop,*         bset      ddrc,x,c.scl       clock low         aslb                          current bit out         bcc       sda0                if 0         bclr      ddrc,x,c.sda       else set to 1         bclr      ddrc,x,c.scl       clock up* don't wait for sync here (but add it if necessary some day)         deca                          count down         bpl       loop         bra       didsda              if ended here*sda0         bset      ddrc,x,c.sda       else set to 1         bclr      ddrc,x,c.scl       clock up* don't wait for sync here (but add it if necessary some day)         deca                          count down         bpl       loopdidsda* now check if ack         bset      ddrc,x,c.scl                 clock low         bclr      ddrc,x,c.sda                 allow sda to go up         bclr      ddrc,x,c.scl                 then clock up again*         brset     portc,x,c.scl,seeack          if clock already high         brset     portc,x,c.scl,seeack          just several microseconds         brset     portc,x,c.scl,seeack          chance, more not         brset     portc,x,c.scl,seeack          acceptable anyway on the nm11         pula                restore a         bra       bsyi2c              return with busy statusseeack         clc                           assume ack will be seen         brclr     portc,x,c.sda,gotack   if ack seen indeed         sec                           otherwiise indicate error         ldab      #e$notf             not found errorgotack         pula                restore a         rts                 *return**** read a bytes at i2C address b at (y)+*i2crdy:         stab      i2caddr             setup i2c address         staa      i2cbcnt             and byte count         bra       rdi2ccm* read a single byte from i2ci2crd:         stab      i2caddr             setup address         ldaa      #1                  just 1 byte         staa      i2cbcnt             setup byte count         bsr       rdi2c               read the byte         bcs       reti2r2             if error         ldaa      /i2cbuff             pickup characterreti2r2         rts** read from device at address in b (return read byte in a)*rdi2c:         ldy       #i2cbuff  point to bufferrdi2ccm         ldx       #regs     point to registers         bclr      ddrc,x,c.scl+c.sda  make sure both are set         brset     portc,x,c.scl+c.sda,goti2c2   if seen high         bra       bsyi2c  if busygoti2c2         ldab      i2caddr             recad address         bsr       sendaddr            send the address first         bcs       retcrd              if error sending address* read datarbloop         ldab      #7                  counter         bset      ddrc,x,c.scl       clock low         bclr      ddrc,x,c.sda        release data line (not in the loop)         set       loop,*         bset      ddrc,x,c.scl       clock low         bclr      ddrc,x,c.scl       clock high ***      brset     portc,x,c.scl,gotdb1          if clock already high***      brset     portc,x,c.scl,gotdb1          if clock already high***      brset     portc,x,c.scl,gotdb1          if clock already high***      brset     portc,x,c.scl,gotdb1          if clock already high***      bra       bsyrd2              if clock stays lowgotdb1         clc                 assume 0         brclr     portc,x,c.sda,reada0          if 0 indeed         sec                           else prepare a 1reada0         rola                collect the data bit         decb                count down         bpl       loop*         staa      0,y                 update data byte         iny                           move pointer*         bset      ddrc,x,c.scl       clock low once again         dec       i2cbcnt             count down         beq       noack2              if all sent         bset      ddrc,x,c.sda        else pull data lownoack2         bclr      ddrc,x,c.scl       clock high again         brset     portc,x,c.scl,gotnoa2   wait clock to be left high         brset     portc,x,c.scl,gotnoa2   wait clock to be left high         brset     portc,x,c.scl,gotnoa2   wait clock to be left high         brset     portc,x,c.scl,gotnoa2   wait clock to be left highbsyrd2         jmp       bsyi2c                  if clock stays lowgotnoa2         ldab      i2cbcnt             all sent?         bne       rbloop              branch not, send next*         bset      ddrc,x,c.scl       clock low again         bset      ddrc,x,c.sda       data low as well         bclr      ddrc,x,c.scl       release clock line         brset     portc,x,c.scl,rnxstp         brset     portc,x,c.scl,rnxstp         brset     portc,x,c.scl,rnxstp         brset     portc,x,c.scl,rnxstp         bra       bsyrd2              if error* send stoprnxstp* send stop after all read         bclr      ddrc,x,c.sda       release sda line - clock high, stop         clc                 no errorretcrd         rts*       END