aboutsummaryrefslogtreecommitdiff
path: root/amforth-6.5/avr8/lib/hardware/25xxx.frt
blob: 295181093042c1458fb56ce820949e6f12e130ad (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131

  6  constant  SEE_WREN
  4  constant  SEE_WRDI
  5  constant  SEE_RDSR
  1  constant  SEE_WRSR
  3  constant  SEE_READ
  2  constant  SEE_WRITE
$AB  constant  SEE_RDID         \ Microchip 25LCxxx only; remove from deep power-down 

 : 25xxx_disable                  \ raise serial EEPROM chip-select line high
   25XXX_CS_A_MASK
   25XXX_CS_A_PORT  c@
   or
   25XXX_CS_A_PORT  c!
 ;

 : 25xxx_enable    ( -- )         \ pull serial EEPROM chip-select line low
   25XXX_CS_A_MASK  invert
   25XXX_CS_A_PORT  c@
   and
   25XXX_CS_A_PORT  c!
 ;

 : 25xxx_c!    ( c  addr  -- )   \ writes char in NOS to serial EEPROM, address in TOS
   25xxx_enable
   25XXX_WREN  spi_send          \ send enable-write command, ignore response
   25xxx_disable
   
   25xxx_enable
   25XXX_WRITE  spi_send         \ send write command, ignore response
   25xxx_sendaddr				  \ send addr (16 or 24 bits)
   spi_send			          \ write byte
   25xxx_disable
   25xxx_wait_rdy
 ;

 : 25xxx_!    ( w  seeaddrl  seeaddrh -- )       \ write word in NOS to serial EEPROM at addr in TOS
   2>r  dup  ><  2r>               \ fast way to prep data in stack ( wl  wh  seeaddrl  seeaddrh )
   over  over  1  0  d+			\ precalc addr of second byte in data
   2>r                             \ save for later  ( wl  wh  seeaddrl  seeaddrh )
   25xxx_c!                  		\ write MSB of word  ( wl )
   2r>                             \ recover addr of next byte  ( wl  seeaddrl+1  seeaddrh )
   25xxx_c!                    	\ write LSB
 ;

 : 25xxx_wait_rdy    ( -- )       \ busy-wait until serial EEPROM finishes writing
   begin
     25xxx_enable
     25XXX_RDSR  spi_xchg  drop  \ send read-status command, ignore response
     0  spi_xchg                 \ send null byte, response is on TOS
     25xxx_disable
     1  and                      \ isolate the WIP (write-in-progress) bit
     1  xor                      \ reverse state of WIP bit
   until                         \ loop until WIP = 0
 ;

 : see_c@      ( addrl addrh -- c )    \ returns byte at 32-bit address in TOS
   25xxx_enable
   25XXX_READ  spi_send          \ send READ command, ignore response
   25xxx_sendaddr				  \ send address (16 or 24 bits)
   0  spi_xchg                   \ send null byte, response is in TOS
   25xxx_disable
 ;

 : 25xxx_c@_blk    ( addr  n  eeaddrl  eeaddrh -- )
   25xxx_enable
   25XXX_READ  spi_send          \ send READ command, ignore response
   25xxx_sendaddr                \ send address (16 or 24 bits)
   0                             \ ( -- addr  n  0 )
   do							  \ for all requested bytes...
     0  spi_xchg                 \ get byte from serial EEPROM
     over                        \ get addr to use
     c!                          \ save the byte
     1+                          \ bump pointer
   loop
   drop                          \ done with address
   25xxx_disable
 ;


 : 25xxx_c!blk    ( addr  n  seeaddrl  seeaddrh  -- )  \ copies N bytes from addr to EEPROM address in TOS/NOS
   25xxx_enable
   25XXX_WREN  spisend           \ need to enable serial EEPROM for writing
   25xxx_disable

   25xxx_enable
   25XXX_WRITE  spi_send         \ send WRITE command, ignore response
   over  over					  \ copy of 32-bit serial EEPROM addr
   25xxx_sendaddr				  \ send addr to serial EEPROM  ( -- addr n seeaddrl seeaddrh )
   rot                           \ ( -- addr seeaddrl seeaddrh n )
   0                             \ ( -- addr seeaddrl seeaddrh n  0 )
   do							  \ for all requested bytes  ( -- addr  seeaddrl  seeaddrh )
     rot dup  i  +               \ addr of byte to fetch  ( -- seeaddrl seeaddrh addr  addr+i )
     c@  spi_send                \ write to serial EEPROM  ( -- seeaddrl seeaddrh addr )
     rot dup  i  +               \ calc addr within serial EEPROM ( -- seeaddrh addr seeaddrl seeaddrl+i )
     7f  and  7f  =              \ last addr in page?; use 7f for 25LC256/512, 3f for AT25128/256
     if
       25xxx_disable             \ done with this page
       25xxx_wait_rdy
       25xxx_enable
       25XXX_WREN  spi_send      \ need to enable serial EEPROM for writing
       25xxx_disable
       25xxx_enable
       25XXX_WRITE  spi_send     \ send WRITE command  ( -- seeaddrh addr seeaddrl )
       rot                       \ set up EEPROM addr ( -- addr  seeaddrl  seeaddrh )
       over  over                \ get a copy
       i  1+  0  d+              \ calc addr of next page  ( -- addr  seeaddrl  seeaddrh seeaddrl  seeaddrh )
       25xxx_sendaddr            \ send addr to serial EEPROM ( -- addr  seeaddrl  seeaddrh)
     else                        \ not start of new page  ( -- seeaddrh addr seeaddrl )
       rot                       \ rearrange  ( -- addr  seeaddrl  seeaddrh )
     then
   loop
   drop
   drop  drop
   25xxx_disable
   25xxx_wait_rdy
 ;


 : 25xxx_init    ( -- )          \ initialize SPI and I/O ports for accessing serial EEPROM
   spi_init
   25XXX_CS_A_DDR  c@
   25XXX_CS_A_MASK  or           \ need to make CS an output
   25XXX_CS_A_DDR  c!
   25xxx_enable
   25XXX_RDID  spi_xchg  drop    \ Microchip 25LCxxx only; take chip out of deep power-down
   0  spi_xchg  drop             \ need to send dummy 16-bit addr, ignore response
   0  spi_xchg  drop
   0  spi_xchg  drop             \ one last null byte, Microchip devices will send ID, ignore it
   25xxx_disable
 ;