4A50 EEPROM access
I'm just about done with 4A50 EEPROM access. I'm a bit surprised by how zippy the EEPROM code can be with a fairly small amount of logic to support it.The biggest limitation is that the EEPROM code must be located in $0000-$3FFF of RAM, $0000-$3FFF of flash, or $8000-$BFFF of flash. Accessing RAM from $4000-$7FFF or ROM from $C000-$FFFF will disrupt EEPROM access.Otherwise, the code that I was expecting to be a real pain in the tusch is actually pretty compact, though it is of necessity split over two 256-byte pages.
mac I2C_MACI2C_START: ldx #$FE stx $6E ; Ensure data is high sta $6F,x ; Access $6F then $6D stx $6E ; Put data high again for first bit ldx #01 bne I2C_sendstartI2C_WRITE: ldx #$01 sta $6D,x ; Hit CLK and set data aslI2C_sendstart: sta $6D,x ; Hit CLK and set data asl sta $6D,x ; Hit CLK and set data asl sta $6D,x ; Hit CLK and set data asl sta $6D,x ; Hit CLK and set data asl sta $6D,x ; Hit CLK and set data asl sta $6D,x ; Hit CLK and set data asl sta $6D,x ; Hit CLK and set data lda #255 sta $6D,x ; Hit CLK and float data nop $6C ; Test data {1} rtsI2C_READ: lda #$FF ; To make things handy with ROL nop $6E ; Assert data ldx #$01 sta $6D,X ; Hit CLK and release data nop $6C,X ; Test data and hit CLK {2} ; SEC if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low nop $6C,X ; Test data and hit CLK {3} ; ROL if high, ASL if low rtsI2C_STOP: ldx #$FE stx $6E ; Release data nop $6D ; Hit CLK nop $6E ; Assert data sta $6F,X ; Hit CLK and release data while CLK is held rts endm org $3E00 rorg $1E00 I2C_MAC sec,asl,asl org $3F00 rorg $1E00 I2C_MAC clc,nop,rol
EEPROM access uses four hotspots: $6C to $6F.Address $6C will check the state of the SDA pin on the EEPROM and set address bit 8 of the upper bank to the observed value.Address $6D will drive SCK high for one cycle.Address $6E will copy bit 7 of the value written to SDA, or 0 if a read was performed; this will occur about 3/4 of the way through the memory cycle.Address $6F will drive SCK high for one cycle and toggle the SDA output about 3/4 of the way through it.The code takes advantage of the fact that zero-page indexed instructions will perform a read of the specified memory address before performing a read or write of the "correct" memory address. So if X is 1, sta $6D,X will read $6D (driving SCK high for one cycle) and then $6E (setting SDA according to bit 7 of the accumulator).Reading the EEPROM is a little trickier than writing, but proper use of $6C takes care of things. Before the read, the accumulator is preloaded with $FF. If the first bit read (the MSB) is set, the carry flag will be set; otherwise the accumulator will be shifted left (so the LSB will be clear, and the carry flag will still be set). For each remaining bit, either an ROL instruction (carry is set, so LSB will be set) or an ASL instruction (clear the LSB, but still set the carry) will be performed.The reads and writes take a little bit of setup time, but not a whole lot; the actual data transfer takes only six cycles per bit.

0 Comments
Recommended Comments
There are no comments to display.