6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu May 09, 2024 3:50 pm

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Optimize my I2C routine?
PostPosted: Fri Apr 14, 2023 11:16 am 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
Trying to improve my I2C routine bitbanging on a 6507+6532 running at 1Mhz

SCL/SDA are on DRB bits 0 and 1. Right now it's clocking out at 55kHz (DDRB and DRB are in ZP). Did I miss anything obvious to improve on that?

I'm trying to optimize away the load modify restores to inc/dec. Seems the second entrypoint i2cbyteout has different states depending on start or repeat byte so I can't use inc/dec for that one - I think..

Code:
i2c_start: ; i2c addr a constant and RW bit is in C
  lda #0
  asl ; Shift in carry
  ora #I2CADDR
  sta outb ; Save addr + rw bit

  lda #SCL_INV ; Start with SCL as INPUT HIGH. If bit 0 is used we can continue from here with inc/dec.
  and DDRB
  sta DDRB

  lda #SDA ; Insure SDA is output low before SCL is LOW
  ora DDRB
  sta DDRB
  lda #SDA_INV
  and PORTB
  sta PORTB

  lda #SCL_INV
  and PORTB
  sta PORTB
  lda DDRB
  ora #SCL
  sta DDRB ; Set SCL LOW by setting it to OUTPUT
  ;inc DDRB ; We're doing this below
  ; Fall through to send address + RW bit

  ; Send an i2c byte - byte is in outb
  ; From here on we can assume OUTPUTs are LOW and INPUTS are HIGH.
  ; Maybe some of the juggling above is not necessary but let's not assume for now
i2cbyteout:
  lda #SDA_INV ; In case this is a data byte we set SDA LOW
  and PORTB
  sta PORTB
  ldx #8
I2CADDRloop: ; At start of loop SDA and SCL are both OUTPUT LOW
  asl outb ; Put MSB in carry
  ; Different state after start and repeat bytes,
  lda DDRB
  ora #SCL
  sta DDRB ; Set SCL LOW by setting it to OUTPUT
;  inc DDRB
  bcc seti2cbit0 ; If data bit was low
  lda DDRB       ; else set it high
  and #SDA_INV
  sta DDRB
  bcs wasone ; BRA
seti2cbit0:
  lda DDRB
  ora #SDA
  sta DDRB
  wasone:
  ;lda DDRB
  ;and #SCL_INV
  ;sta DDRB ; Set SCL HIGH by setting it to input; Let SCL go HIGH by setting it to input
  dec DDRB
  dex
  bne I2CADDRloop
  ;lda DDRB
  ;ora #SCL
  ;sta DDRB ; Set SCL LOW by setting it to OUTPUT ; Set SCL low after last bit
  inc DDRB
  lda DDRB ; Set SDA to INPUT
  and #SDA_INV
  sta DDRB
  ;lda DDRB
  ;and #SCL_INV
  ;sta DDRB ; Set SCL HIGH by setting it to input
  dec DDRB
  lda PORTB ; Check ACK bit
  clc
  and #SDA
  bne nack
  sec ; Set carry to indicate ACK
  nack:
  ;lda DDRB
  ;ora #SCL
  ;sta DDRB ; Set SCL LOW by setting it to OUTPUT
  inc DDRB
  rts

i2c_stop:
  lda DDRB ; SDA low
  ora #SDA
  sta DDRB
  ;lda DDRB
  ;and #SCL_INV
  ;ta DDRB ; Set SCL HIGH by setting it to input
  dec DDRB
  lda DDRB       ; Set SDA high after SCL == Stop condition.
  and #SDA_INV
  sta DDRB
  rts

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 14, 2023 7:00 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8432
Location: Southern California
Be sure you've considered http://wilsonminesco.com/6502primer/GENRLI2C.ASM .  It does use a couple of CMOS instructions which you'll have to replace with more instructions to run on the NMOS 6507, but its efficiency is pretty good, and its readability is better.  The code there is in several forms.

_________________
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?


Top
 Profile  
Reply with quote  
PostPosted: Fri Apr 14, 2023 10:35 pm 
Offline
User avatar

Joined: Sun Dec 26, 2021 8:27 pm
Posts: 182
GARTHWILSON wrote:
Be sure you've considered http://wilsonminesco.com/6502primer/GENRLI2C.ASM .  It does use a couple of CMOS instructions which you'll have to replace with more instructions to run on the NMOS 6507, but its efficiency is pretty good, and its readability is better.  The code there is in several forms.


Thanks for taking a look. The c02 instructions aside it actually looks like your send byte routine is basically the same, almost down to the instruction.

Code:
 SEND_I2C_BYTE:                  ; Start with byte in A, and clock low.  Ends with I2C_ACK?.
        STA     I2C_TEMP        ; Store the byte in a variable so we can use A with TSB & TRB for data line.
        LDA     #10000000B      ; Init A for mask for TRB & TSB below.  A does not get disturbed below.
        LDX     #8              ; We will do 8 bits.
 sIb2:     TRB  DDRA            ; Release data line.  This is like I2C_DATA_UP but saves 1 instruction.
           ASL  I2C_TEMP        ; Get next bit to send and put it in the C flag.
           BCS  sIb1
              TSB DDRA          ; If the bit was 0, pull data line down by making it an output.
 sIb1:     DEC  DDRA            ; Do a high pulse on the clock line.  Remember there's a 0 in the output
           INC  DDRA            ; register bit, and DEC'ing DDRA makes that bit an input, so it can float up.
           DEX                  ;    IOW, it's backwards from what it seems.
        BNE     sIb2
        JMP     I2C_ACK?        ; (JSR, RTS)
 ;------------------


I’m still scratching my head over the fact that when I optimize away the SCL RMW’s to one INC, SCL never goes low.
PB6 & 7 are busy so SDA is on bit 1.

_________________
---
New new new new new video out! Serial Bootloader for my 65uino
Also, check out: I2C on a 6502 Single Board Computer
and Complete hardware overview of my 6502 SBC R1 :)


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: John West and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: