|
- ; *** EEPROM write ***
- ; Listen to UART expecting tty-escaped "pingpong" (from tools/) communication.
- ;
- ; Each of those received bytes is written to the EEPROM, starting at addr 0.
- ; that byte is then re-read and sent back to the UART, tty-escaped.
- ;
- ; Addr selection is done through 2 chained '164, data in/out is done directly
- ; with PD7:2 for bits 7:2 and PB1:0 for bits 1:0 (PD1 and PD0 are used for
- ; UART).
- ;
- ; *** Timing, matching and CE ***
- ;
- ; A lot of trial-and-errors went into those NOPs being place to give time for
- ; latching. All these timing are well, well above maximums given in the specs,
- ; but when I wasn't going well, well above those specs, I was experiencing
- ; read/write errors. It seems we live in an imperfect world!
- ;
- ; I'm also not sure, in "writedata", whether toggling CE along with WE is
- ; actually needed, but until I did, I was experiencing random write failures.
- ; So, we end up with this...
- ;
- ; *** Register Usage ***
- ;
- ; r0: holds whether last received char was tty-escaped (0 = no, 1=yes)
- ; r16: generic tmp
- ; r17: generic tmp
- ; r20: Byte to send to the "data" SR. Wired to D0-D7.
- ; r21: "high" byte, to send to the "addr" SR. Wired to A8-15
- ; r22: "low" byte, to send to the "addr" SR. Wired to A0-7
- ; r23: tmp value to use for sending to the "addr" SR
-
- .include "m328Pdef.inc"
-
- ; *** Pins ***
- .equ SRCP = PORTB2
- .equ SRDS = PORTB1
- .equ FLWE = PORTB3
- .equ FLOE = PORTB4
- .equ FLCE = PORTB5 ; WARNING: same as LED
-
- ; *** Consts ***
- .equ BAUD_PRESCALE = 103 ; 9600 bauds at 16mhz
-
- rjmp main
-
- ; *** Code ***
- ; Waits until a char is read, then put it in R20
- ; Perform TTY-escape transparently.
- uartrd:
- lds r16, UCSR0A
- sbrs r16, RXC0 ; RXC0 is set? skip rjmp and fetch char.
- rjmp uartrd
- lds r20, UDR0
- ; is this the escape char?
- cpi r20, 0x20
- brne uartrd_0
- ; escape char
- ; We "pong" the escape right away.
- rcall uartwr
- inc r0
- rjmp uartrd
- uartrd_0:
- ; should we escape?
- tst r0
- breq uartrd_1
- ; yes
- andi r20, 0x7f
- uartrd_1:
- ret
-
- ; Sends char in r20 to UART
- ; Perform TTY-escape transparently.
- uartwr:
- lds r16, UCSR0A
- sbrs r16, UDRE0 ; wait until send buffer is empty
- rjmp uartwr
- ; should we escape?
- tst r0
- breq uartwr_0
- ; we need to escape
- ori r20, 0x80
- clr r0
- uartwr_0:
- sts UDR0, r20
- ret
-
- ; send r23 to addr shift register.
- ; We send highest bits first so that Q7 is the MSB and Q0 is the LSB
- sendaddr:
- ldi r16, 8 ; we will loop 8 times
- cbi PORTB, SRDS
- sbrc r23, 7 ; if latest bit isn't cleared, set SER_DP high
- sbi PORTB, SRDS
- ; toggle SRCP, not waiting between pulses. The CD74AC164 at 5V has a
- ; 5.9ns CP min pulse width. We can't match that at 16mhz. No need to
- ; wait.
- cbi PORTB, SRCP
- sbi PORTB, SRCP
- lsl r23 ; shift our data left
- dec r16
- brne sendaddr+1 ; not zero yet? loop! (+1 to avoid reset)
- ret
-
- ; send r20 to EEPROM's I/O7:0 through PD7:2 and PB1:0
- writedata:
- cbi PORTB, FLCE
- ; addr is latched on WE falling edge
- cbi PORTB, FLWE
-
- ; send bits 7:2
- mov r16, r20
- andi r16, 0xfc
- in r17, PORTD
- andi r17, 0x03
- or r16, r17
- out PORTD, r16
- ; send bits 1:0
- mov r16, r20
- andi r16, 0x03
- in r17, PORTB
- andi r17, 0xfc
- or r16, r17
- out PORTB, r16
-
- ; data is latched on rising edge
- sbi PORTB, FLWE
- sbi PORTB, FLCE
- nop ; Give the AT28 time to latch
- nop
- nop
- ret
-
- ; push r20 to the rom and increase the memory counter
- nextaddr:
- ; first, set up addr
- mov r23, r21
- rcall sendaddr
- mov r23, r22
- rcall sendaddr
- inc r22
- brne nextaddr_0 ; no overflow? skip
- inc r21
- nextaddr_0:
- ret
-
- ; wait until I/O7 stops toggling
- waitio7:
- cbi PORTB, FLCE
- cbi PORTB, FLOE
- nop ; Give the AT28 time to latch
- nop
- nop
- in r16, PIND
- sbi PORTB, FLOE
- sbi PORTB, FLCE
- andi r16, 0xfc
- cbi PORTB, FLCE
- cbi PORTB, FLOE
- nop ; Give the AT28 time to latch
- nop
- nop
- in r17, PIND
- sbi PORTB, FLOE
- sbi PORTB, FLCE
- andi r17, 0xfc
- cp r16, r17
- brne waitio7
- ret
-
- ; read EEPROM's I/O7:0 through PD7:2 and PB1:0 into r20
- readdata:
- cbi PORTB, FLCE
- cbi PORTB, FLOE
- nop ; Give the AT28 time to latch
- nop
- nop
- ; read bits 7:2
- in r20, PIND
- andi r20, 0xfc
- ; read bits 1:0
- in r16, PINB
- andi r16, 0x03
- or r20, r16
- sbi PORTB, FLOE
- sbi PORTB, FLCE
- ret
-
- ; Set PD7:2 and PB1:0 to output
- ioout:
- ldi r16, 0xfc ; PD7:2
- out DDRD, r16
- ldi r16, 0x3f ; PB5:0 (CP, WE, OE and CE too)
- out DDRB, r16
- ret
-
- ; Set PD7:2 and PB1:0 to input
- ioin:
- ldi r16, 0x03 ; PD7:2
- out DDRD, r16
- ldi r16, 0x3c ; PB1:0
- out DDRB, r16
- ret
-
- main:
- ldi r16, low(RAMEND)
- out SPL, r16
- ldi r16, high(RAMEND)
- out SPH, r16
-
- sbi PORTB, FLWE
- sbi PORTB, FLOE
- sbi PORTB, FLCE
-
- ; Clear counters and flags
- clr r0
- clr r21
- clr r22
-
- ; Setup UART
- ldi R16, low(BAUD_PRESCALE)
- sts UBRR0L, r16
- ldi r16, high(BAUD_PRESCALE)
- sts UBRR0H, r16
-
- ldi r16, (1<<RXEN0) | (1<<TXEN0)
- sts UCSR0B, r16
-
- loop:
- rcall uartrd
- rcall ioout
- rcall nextaddr
- rcall writedata
- rcall ioin
- rcall waitio7
- rcall readdata
- rcall uartwr
- rjmp loop
|