i2cutils 45.7 KB
Newer Older
Neil Turton's avatar
Neil Turton committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
; Copyright 1996 Acorn Computers Ltd
;
; Licensed under the Apache License, Version 2.0 (the "License");
; you may not use this file except in compliance with the License.
; You may obtain a copy of the License at
;
;     http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing, software
; distributed under the License is distributed on an "AS IS" BASIS,
; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
; See the License for the specific language governing permissions and
; limitations under the License.
;
; > $.Source.PMF.i2cutils

; Authors JBiggs (m2), PFellows, TDobson, AGodwin

Neil Turton's avatar
Neil Turton committed
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
; ***********************************
; ***    C h a n g e   L i s t    ***
; ***********************************

; Date       Name  Description
; ----       ----  -----------
; 28-Mar-95  JRH   Added support for E2ROMs and/or CMOS, conditioned on
;                  E2ROMSupport which is defined elsewhere
;                  Uses RTCFitted and NVRamSize in KernelWS
; 03-Jul-96  JRH   Took out code conditioned on :LNOT: NewClockChip
;                  Fixed support for E2ROM. E2 works in the same gross way as
;                  CMOS. Any E2 fitted > 256 bytes will not be accessed by these
;                  routines.
; amg 7/12/96 Renaissance. Leave this file as is, allowing the E2ROMSupport
;             switch to disable non-STB bits
Kevin Bracey's avatar
Kevin Bracey committed
34 35 36
; 12-Jun-97  TMD   (Really) fix OTP access problem.
; 17-Sep-98  KJB   Add support for 16K 24C128 EEPROM.
; 21-Sep-98  KJB   Add OS_NVMemory SWI.
37
; 30-Jul-99  KJB   Add support for 8K 24C64 EEPROM.
38
; 23-Sep-99  KJB   Remove support for 24C64, add support for 4K and 8K protectable ATMEL parts.
Neil Turton's avatar
Neil Turton committed
39 40 41

PhysChecksum	*	(((CheckSumCMOS + &30) :MOD: &F0) + &10)

Kevin Bracey's avatar
Kevin Bracey committed
42 43
PollMax		*	150	; Number of times to poll for an Ack (increase if you clock faster - need to
                                ; allow 5ms for write cycle).
Neil Turton's avatar
Neil Turton committed
44 45

; Device addresses
Kevin Bracey's avatar
Kevin Bracey committed
46
RTCAddress		*	&a0     ; traditional RTC / 240 byte CMOS
Neil Turton's avatar
Neil Turton committed
47
  [	E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
48 49 50
E2ROMAddress		*	&a8     ; 24C08 device - 512 byte or 1K
E2ROMAddress2K		*	&e0     ; 24C174 device - 2K
E2ROMAddress2K_OTP	*	&60     ; 24C174 device - OTP section
51 52
E2ROMAddress4K          *       &a4     ; 24C32 device - 4K (top 1K protectable)
E2ROMAddress8K          *       &a2     ; 24C64 device - 8K (top 2K protectable)
Kevin Bracey's avatar
Kevin Bracey committed
53
E2ROMAddress16K         *       &a8     ; 24C128 device - 16K
Neil Turton's avatar
Neil Turton committed
54 55
  ]

Neil Turton's avatar
Neil Turton committed
56 57
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
58
;	HexToBCD - Convert byte in hex to BCD
Neil Turton's avatar
Neil Turton committed
59
;
Neil Turton's avatar
Neil Turton committed
60
; in:	R0 = byte in hex
Neil Turton's avatar
Neil Turton committed
61
;
Neil Turton's avatar
Neil Turton committed
62 63
; out:	R0 = byte in BCD (ie R0 := (R0 DIV 10)*16 + R0 MOD 10)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
64 65 66
;

HexToBCD ROUT
Neil Turton's avatar
Neil Turton committed
67 68 69 70 71
	Push	"R1,R2, R14"
	MOV	R1, #10
	DivRem	R2, R0, R1, R14			; R2=R0 DIV 10; R0=R0 MOD 10
	ADD	R0, R0, R2, LSL #4
	Pull	"R1,R2, PC"
Neil Turton's avatar
Neil Turton committed
72 73 74

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
75
;	BCDToHex - Convert byte in BCD to hex
Neil Turton's avatar
Neil Turton committed
76
;
Neil Turton's avatar
Neil Turton committed
77
; in:	R0 = byte in BCD (ie x*16 + y)
Neil Turton's avatar
Neil Turton committed
78
;
Neil Turton's avatar
Neil Turton committed
79 80
; out:	R0 = byte in hex (ie x*10 + y)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
81 82 83
;

BCDToHex ROUT
Neil Turton's avatar
Neil Turton committed
84 85 86 87 88
	Push	"R14"
	MOV	R14, R0, LSR #4			; R14 := x
	ADD	R14, R14, R14, LSL #1		; R14 := x*3
	SUB	R0, R0, R14, LSL #1		; R0 := R0 - x*6 = x*10
	Pull	"PC"
Neil Turton's avatar
Neil Turton committed
89 90 91

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
92
;	SetC1C0 - Set clock and data lines to values in R1 and R0 respectively
Neil Turton's avatar
Neil Turton committed
93
;
Neil Turton's avatar
Neil Turton committed
94
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
95 96 97
;

SetC1C0 ROUT
Neil Turton's avatar
Neil Turton committed
98 99
	Push	"R0-R2,R14"
	ADD	R0, R0, R1, LSL #1	; R0 := C0 + C1*2
Neil Turton's avatar
Neil Turton committed
100

Neil Turton's avatar
Neil Turton committed
101 102 103 104 105 106 107 108 109 110 111
	[ AssemblingArthur :LOR: Module
	MOV	R2, #0				; prepare to index soft copy
	LDRB	R1, [R2, #IOCControlSoftCopy]	; read soft copy
	BIC	R1, R1, #&03			; clear clock and data
	ORR	R0, R1, R0			; put in new clock and data
	ORR	R0, R0, #&C0			; make sure two test bits are
						; always set to 1 !
	STRB	R0, [R2, #IOCControlSoftCopy]	; store back to soft copy
	|
	ORR	R0, R0, #&FC			; set other bits to 1
	]
Neil Turton's avatar
Neil Turton committed
112

Neil Turton's avatar
Neil Turton committed
113 114
	MOV	R2, #IOC
	STRB	R0, [R2, #IOCControl]
Neil Turton's avatar
Neil Turton committed
115

Kevin Bracey's avatar
Kevin Bracey committed
116 117 118 119 120 121 122 123 124 125 126 127
 [ ClockNVMemoryFast
        [ :LNOT: :DEF: TestHarness
        MOV	R0, #0
        LDRB	R0, [R0, #NVRamSpeed]
        |
        LDRB	R0, NVSpeed
        ]
        TEQ     R0, #0
        MOVEQ   R0, #10                         ; default value if speed not checked yet
 |
        MOV     R0, #10                         ; 5s delay
 ]
Neil Turton's avatar
Neil Turton committed
128
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
129

Neil Turton's avatar
Neil Turton committed
130
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
131 132 133

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
134
;	DoMicroDelay - Delay for >= R0/2 microseconds
Neil Turton's avatar
Neil Turton committed
135
;
Neil Turton's avatar
Neil Turton committed
136 137 138
; in:	R0 = time delay in 1/2 microsecond units
;	R2 -> IOC
;	On ARM600, we may or may not be in a 32-bit mode
Neil Turton's avatar
Neil Turton committed
139
;
Neil Turton's avatar
Neil Turton committed
140
; out:	R0,R1 corrupted
Neil Turton's avatar
Neil Turton committed
141 142 143
;

DoMicroDelay ROUT
Neil Turton's avatar
Neil Turton committed
144
	Push	R14
Neil Turton's avatar
Neil Turton committed
145

Neil Turton's avatar
Neil Turton committed
146 147
	STRB	R0, [R2, #Timer0LR]	; copy counter into output latch
	LDRB	R1, [R2, #Timer0CL]	; R1 := low output latch
Neil Turton's avatar
Neil Turton committed
148
10
Neil Turton's avatar
Neil Turton committed
149 150 151 152 153 154 155
	STRB	R0, [R2, #Timer0LR]	; copy counter into output latch
	LDRB	R14, [R2, #Timer0CL]	; R14 := low output latch
	TEQ	R14, R1			; unchanged ?
	BEQ	%BT10			; then loop
	MOV	R1, R14			; copy anyway
	SUBS	R0, R0, #1		; decrement count
	BNE	%BT10			; loop if not finished
Neil Turton's avatar
Neil Turton committed
156

Neil Turton's avatar
Neil Turton committed
157
	Pull	PC
Neil Turton's avatar
Neil Turton committed
158

Neil Turton's avatar
Neil Turton committed
159
	LTORG
Neil Turton's avatar
Neil Turton committed
160 161 162

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
163
;	ClockData - Clock a bit of data down the IIC bus
Neil Turton's avatar
Neil Turton committed
164
;
Neil Turton's avatar
Neil Turton committed
165
; in:	R0 = data bit
Neil Turton's avatar
Neil Turton committed
166
;
Neil Turton's avatar
Neil Turton committed
167
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
168 169 170
;

ClockData ROUT
Neil Turton's avatar
Neil Turton committed
171
	Push	"R1, R14"
Neil Turton's avatar
Neil Turton committed
172

Neil Turton's avatar
Neil Turton committed
173 174
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
175 176 177 178 179

 [ {TRUE}
; Disable interrupts to ensure clock hi with data hi is only transient
; This allows BMU to detect idle condition by polling

Neil Turton's avatar
Neil Turton committed
180 181 182
	MOV	R1,PC
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
183
 ]
Neil Turton's avatar
Neil Turton committed
184 185
	MOV	R1, #1			; Clock hi
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
186 187 188

; Delay here must be >= 4.0 microsecs

Neil Turton's avatar
Neil Turton committed
189 190
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
191

Neil Turton's avatar
Neil Turton committed
192
	Pull	"R1, PC",,^
Neil Turton's avatar
Neil Turton committed
193

Neil Turton's avatar
Neil Turton committed
194 195 196 197 198
ClockData0 ROUT				; Clock a zero bit
	Push	"R0, R14"
	MOV	R0, #0
	BL	ClockData
	Pull	"R0, PC",,^
Neil Turton's avatar
Neil Turton committed
199 200 201

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
202
;	Start - Send the Start signal
Neil Turton's avatar
Neil Turton committed
203
;
Neil Turton's avatar
Neil Turton committed
204
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
205 206
;

Neil Turton's avatar
Neil Turton committed
207 208
Start	ROUT
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
209

Neil Turton's avatar
Neil Turton committed
210 211 212
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
213

Kevin Bracey's avatar
Kevin Bracey committed
214
; Delay here must be >= 4.7 microsecs (1.3 for fast device)
Neil Turton's avatar
Neil Turton committed
215

Neil Turton's avatar
Neil Turton committed
216 217 218
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
219

Kevin Bracey's avatar
Kevin Bracey committed
220
 [ :LNOT: ClockNVMemoryFast
Neil Turton's avatar
Neil Turton committed
221 222
; Hold start condition for BMU

Neil Turton's avatar
Neil Turton committed
223
	MOV	R2, #IOC
Kevin Bracey's avatar
Kevin Bracey committed
224
        MOV     R0, #10
Neil Turton's avatar
Neil Turton committed
225
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
226 227
 ]

Kevin Bracey's avatar
Kevin Bracey committed
228
; Delay here must be >= 4.0 microsecs (0.6 for fast device)
Neil Turton's avatar
Neil Turton committed
229

Neil Turton's avatar
Neil Turton committed
230 231 232
	MOV	R0, #0			; clock LO, data LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
233

Neil Turton's avatar
Neil Turton committed
234
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
235 236 237

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
238
;	Acknowledge - Check acknowledge after transmitting a byte
Neil Turton's avatar
Neil Turton committed
239
;
Neil Turton's avatar
Neil Turton committed
240 241 242
; out:	All registers preserved
;	V=0 => acknowledge received
;	V=1 => no acknowledge received
Neil Turton's avatar
Neil Turton committed
243 244 245
;

Acknowledge ROUT
Neil Turton's avatar
Neil Turton committed
246
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
247

Neil Turton's avatar
Neil Turton committed
248 249 250
	MOV	R0, #1			; clock LO, data HI
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
251 252 253 254 255

 [ {TRUE}
; Disable interrupts to ensure clock hi with data hi is only transient
; This allows BMU to detect idle condition by polling

Neil Turton's avatar
Neil Turton committed
256 257 258 259
	MOV	R1,PC
	Push	"R1"
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
260
 ]
Neil Turton's avatar
Neil Turton committed
261 262 263
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
264

Kevin Bracey's avatar
Kevin Bracey committed
265
; Delay here must be >= 4.0 microsecs (0.6 for fast device)
Neil Turton's avatar
Neil Turton committed
266

Neil Turton's avatar
Neil Turton committed
267 268
	MOV	R2, #IOC
	LDRB	R2, [R2, #IOCControl]	; get the data from IOC
Neil Turton's avatar
Neil Turton committed
269

Neil Turton's avatar
Neil Turton committed
270 271 272
	MOV	R0, #0
	MOV	R1, #0			; clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
273 274

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
275 276
	Pull	"R1"
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
277 278
 ]

Neil Turton's avatar
Neil Turton committed
279 280 281 282 283
	TST	R2, #1			; should be LO for correct acknowledge
	MOV	R2, PC
	BICEQ	R2, R2, #V_bit		; clear V if correct acknowledge
	ORRNE	R2, R2, #V_bit		; set V if no acknowledge
	TEQP	R2, #0
Neil Turton's avatar
Neil Turton committed
284

Neil Turton's avatar
Neil Turton committed
285
	Pull	"R0-R2,PC"
Neil Turton's avatar
Neil Turton committed
286 287 288

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
289
;	Stop - Send the Stop signal
Neil Turton's avatar
Neil Turton committed
290
;
Neil Turton's avatar
Neil Turton committed
291
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
292 293
;

Neil Turton's avatar
Neil Turton committed
294 295
Stop	ROUT
	Push	"R0,R1,R14"
Neil Turton's avatar
Neil Turton committed
296

Neil Turton's avatar
Neil Turton committed
297 298 299
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
300

Kevin Bracey's avatar
Kevin Bracey committed
301
; Delay here must be >= 4.0 microsecs (0.6 for fast device)
Neil Turton's avatar
Neil Turton committed
302

Neil Turton's avatar
Neil Turton committed
303 304 305
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
306

Neil Turton's avatar
Neil Turton committed
307
	Pull	"R0,R1,PC",,^
Neil Turton's avatar
Neil Turton committed
308 309 310

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
311
;	TXByte - Transmit a byte
Neil Turton's avatar
Neil Turton committed
312
;
Neil Turton's avatar
Neil Turton committed
313
; in:	R0 = byte to be transmitted
Neil Turton's avatar
Neil Turton committed
314
;
Neil Turton's avatar
Neil Turton committed
315
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
316 317
;

Neil Turton's avatar
Neil Turton committed
318 319 320
TXByte	ROUT
	Push	"R0-R2,R14"
	MOV	R1, #&80		; 2^7 the bit mask
Kevin Bracey's avatar
Kevin Bracey committed
321
	MOV	R2, R0			; byte goes into R2
Neil Turton's avatar
Neil Turton committed
322
10
Neil Turton's avatar
Neil Turton committed
323 324 325 326 327 328
	ANDS	R0, R2, R1		; zero if bit is zero
	MOVNE	R0, #1
	BL	ClockData		; send the bit
	MOVS	R1, R1, LSR #1
	BNE	%BT10
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
329 330 331

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
332 333 334 335 336 337
;	StartTXPollAck - Transmit start and a byte and poll for acknowledge
;
;	This is intended for devices with a slow internal write cycle which
;	don't ack until the write cycle is finished ( eg ATMEL AT24C01A/x )
;
; in:	R0 = byte to be transmitted
Neil Turton's avatar
Neil Turton committed
338
;
Neil Turton's avatar
Neil Turton committed
339
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
340 341
;

Neil Turton's avatar
Neil Turton committed
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
StartTXPollAck	ROUT
	Push	"R1,R14"
	MOV	R1, #0
10
	INC	R1
	CMP	R1, #PollMax
	Pull	"R1,pc", EQ

	BL	Start
	BL	TXByte
	BL	Acknowledge
	BVS	%BT10
 [	{FALSE}
	BREG	R1, "i2c tries:"
 ]
	Pull	"R1,pc",,^
Neil Turton's avatar
Neil Turton committed
358

Neil Turton's avatar
Neil Turton committed
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
; *****************************************************************************
;
;	RXByte - Receive a byte
;
; out:	R0 = byte received
;	All other registers preserved, including PSR
;

RXByte	ROUT
	Push	"R1-R4, R14"
	MOV	R3, #0			; byte:=0
	MOV	R2, #IOC
	MOV	R4, #7

	MOV	R0, #1			; clock LO, data HI
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
376 377 378 379 380
10
 [ {TRUE}
; Disable interrupts to ensure clock hi with data hi is only transient
; This allows BMU to detect idle condition by polling

Neil Turton's avatar
Neil Turton committed
381 382 383 384
	MOV	R1,PC
	Push	"R1"
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
385
 ]
Neil Turton's avatar
Neil Turton committed
386 387 388
	MOV	R0, #1			; pulse clock HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
389

Neil Turton's avatar
Neil Turton committed
390 391 392
	LDRB	R1, [R2, #IOCControl]	; get the data from IOC
	AND	R1, R1, #1
	ADD	R3, R1, R3, LSL #1	; byte:=byte*2+(IOC?0)AND1
Neil Turton's avatar
Neil Turton committed
393

Neil Turton's avatar
Neil Turton committed
394 395 396
	MOV	R0, #1			; return clock LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
397 398

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
399 400
	Pull	"R1"
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
401
 ]
Neil Turton's avatar
Neil Turton committed
402 403 404 405 406 407 408 409 410 411 412 413 414
	SUBS	R4, R4, #1
	BCS	%BT10

	MOV	R0, R3			; return the result in R0
	Pull	"R1-R4, PC",,^

; *****************************************************************************

HTBTA	ROUT
	Push	R14
	BL	HexToBCD
	BL	TXAck
	Pull	PC
Neil Turton's avatar
Neil Turton committed
415

Neil Turton's avatar
Neil Turton committed
416 417 418 419 420 421 422 423 424 425 426 427
TXAck	ROUT
	Push	R14
	BL	TXByte
	BL	Acknowledge
	Pull	PC

CD0RBTH ROUT
	Push	R14
	BL	ClockData0
	BL	RXByte
	BL	BCDToHex
	Pull	PC
Neil Turton's avatar
Neil Turton committed
428 429 430

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
431
;	Write - Write a byte of CMOS RAM specified by logical address
Neil Turton's avatar
Neil Turton committed
432
;
Neil Turton's avatar
Neil Turton committed
433 434
; in:	R0 = address in CMOS RAM
;	R1 = data
Neil Turton's avatar
Neil Turton committed
435
;
Neil Turton's avatar
Neil Turton committed
436
; out:	All registers preserved
Neil Turton's avatar
Neil Turton committed
437 438
;

Kevin Bracey's avatar
Kevin Bracey committed
439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
WriteWithError ROUT
        Push    "R0-R4, R14"
        BL      MangleCMOSAddress
        BCC     %FT05

        ADD     R13, R13, #4            ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotWriteable
 [ International
        BL      TranslateError
 ]
        Pull    "R1-R4,R14"
        ORRS    PC, LR, #V_bit

        MakeErrorBlock CoreNotWriteable

Write
Neil Turton's avatar
Neil Turton committed
455 456 457
	Push	"R0-R4, R14"
	BL	MangleCMOSAddress
	Pull	"R0-R4, PC", CS		; if invalid, then exit
Kevin Bracey's avatar
Kevin Bracey committed
458 459 460 461 462
05
  [ E2ROMSupport
        CMP     r0, #&10
        Pull    "R0-R4, PC", CC         ; don't write to OTP section
  ]
Neil Turton's avatar
Neil Turton committed
463

464 465
        MOV     R14, #0                 ; don't write to protected section
        LDRB    R14, [R14, #NVRamWriteSize]
466
        CMP     R0, R14, LSL #8         ; (note assumption that NVRamWriteSize is
467 468
        Pull    "R0-R4, PC", HS         ; outside mangled region).

Neil Turton's avatar
Neil Turton committed
469 470 471 472 473 474 475 476 477
	MOV	R2, R0
	MOV	R3, R1
 [ ChecksumCMOS
	BL	ReadStraight		; calculate new checksum :
	MOV	R4, R0
	MOV	R0, #PhysChecksum
	BL	ReadStraight
	SUB	R0, R0, R4		; = oldsum - oldcontents
	ADD	R4, R0, R3		;          + newcontents
Neil Turton's avatar
Neil Turton committed
478

Neil Turton's avatar
Neil Turton committed
479 480 481 482
	AND	R4, R4, #&FF
	CMPS	R2, #PhysChecksum	; don't write new checksum ...
	ORREQ	R4, R4, #&1000000	; if checksum is being written
 ]
Neil Turton's avatar
Neil Turton committed
483 484
10
 [ CacheCMOSRAM
Kevin Bracey's avatar
Kevin Bracey committed
485 486 487 488 489 490
	CMP	r2, #&100		; check small cache limit
	BCS	%FT15
  [ :LNOT: :DEF: TestHarness
	LDR	R1, =CMOSRAMCache	; update cache, but always write to
  |
        ADR     R1, i2cWorkSpace
Neil Turton's avatar
Neil Turton committed
491 492
  ]
	STRB	R3, [R1, R2]		; real hardware as well
Kevin Bracey's avatar
Kevin Bracey committed
493
15
Neil Turton's avatar
Neil Turton committed
494 495 496 497 498 499 500
 ]
 [ E2ROMSupport
	MOV	R0, R2
	BL	GetI2CAddress		; convert to device address + offset
	MOV	R2, R0			; save the offset
 |
	MOV	R1, #RTCAddress
Neil Turton's avatar
Neil Turton committed
501 502
 ]

Neil Turton's avatar
Neil Turton committed
503 504
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
505

Kevin Bracey's avatar
Kevin Bracey committed
506 507 508 509 510
        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
Neil Turton's avatar
Neil Turton committed
511
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
512

Neil Turton's avatar
Neil Turton committed
513 514
	MOV	R0, R3			; data
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
515

Neil Turton's avatar
Neil Turton committed
516 517 518 519 520 521 522 523 524
	BL	Stop
	[ ChecksumCMOS
	TST	R4, #&1000000		; loop again to write new checksum
	MOV	R3, R4
	MOV	R2, #PhysChecksum
	ORR	R4, R4, #&1000000	; but ensure it only happens once
	BEQ	%BT10
	]
	Pull	"R0-R4, PC"
Neil Turton's avatar
Neil Turton committed
525

Kevin Bracey's avatar
Kevin Bracey committed
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542
; *****************************************************************************
;
;       WriteBlock - Write a block of CMOS RAM specified by logical address
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy from
;       R2 = length
;
; out:  All registers preserved
;


WriteBlock ROUT
        Push    "R0-R4,R14"
  [     E2ROMSupport
        [ :LNOT: :DEF: TestHarness
        MOV	R14, #0
543
        LDRB    R4, [R14, #NVRamWriteSize]
Kevin Bracey's avatar
Kevin Bracey committed
544
        LDRB	R14, [R14, #NVRamSize]
545
        MOV     R4, R4, LSL #8
Kevin Bracey's avatar
Kevin Bracey committed
546 547
        |
        LDRB	R14, NVSize
548
        MOV     R4, R14
Kevin Bracey's avatar
Kevin Bracey committed
549 550 551 552
        ]
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
553
        MOV     R4, R14
Kevin Bracey's avatar
Kevin Bracey committed
554 555 556 557 558 559 560 561 562 563
  ]

        CMP     R0, R14
        BHS     %FT90

        ADDS    R3, R0, R2              ; R3 = end address - check unsigned overflow
        BCS     %FT90
        CMP     R3, R14
        BHI     %FT90

564 565 566 567 568 569
        CMP     R0, R4                  ; ignore writes totally outside writable area
        BHS     %FT80

        SUBS    R14, R3, R4
        SUBGT   R2, R2, R14             ; truncate writes partially outside writable area

Kevin Bracey's avatar
Kevin Bracey committed
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749
        TEQ     R2, #0
        BEQ     %FT80

        CMP     R0, #CheckSumCMOS       ; are we going to write the checksum byte?
        BHI     %FT03
        CMP     R3, #CheckSumCMOS
        BHS     %FT05

03
; we're not writing the checksum byte manually, so we need to update it
        MOV     R4, R1
        MOV     R1, #0
        BL      ChecksumBlock           ; find the checksum of what we're about to
        ORR     R3, R1, #&80000000      ; overwrite
        MOV     R1, R4
        B       %FT08

05      MOV     R3, #0
08      MOV     R4, #0
10      BL      WriteSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10

        TST     R3, #&80000000          ; were we going to write the checksum?
        BEQ     %FT80

        MOV     R0, #CheckSumCMOS
        BL      Read                    ; get old checksum byte
        ADD     R0, R0, R4              ; add new data checksum
        SUB     R1, R0, R3              ; subtract old checksum
        MOV     R0, #CheckSumCMOS
        BL      Write                   ; write back new checksum

80
        Pull    "R0-R4,PC"

90
        ADD     SP, SP, #4              ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotWriteable
 [ International
        BL      TranslateError
 ]
95
        Pull    "R1-R4,LR"
        ORRS    PC, LR, #V_bit

; *****************************************************************************
;
;       WriteSubBlock - Write a block of CMOS RAM specified by logical address.
;                       Assumes the address is valid, and will only read as much
;                       as it can in a single IIC transaction.
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy from
;       R2 = length
;
; out:  R0-R2 updated to reflect the amount written.
;       R4 incremented by sum of bytes written.
;
WriteSubBlock ROUT
        Push    "R3,R5-R6,R14"
        MOV     R6, R4
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&F0                ; [C0..F0) -> [10..40) cached
        MOVLO   R3, #&F0
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
        BHS     %FT10

; [F0..100) -> not written
        MOV     R3, #&100
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
        SUB     R14, R3, R0
        ADD     R0, R0, R14
        ADD     R1, R1, R14
        SUB     R2, R2, R14
        Pull    "R3,R5-R6,PC"

; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
 [ E2ROMSupport
; R3 = logical end of possible transaction (exclusive). Now check we don't cross page boundaries.
        [ :LNOT: :DEF: TestHarness
        MOV	R14, #0
        LDRB	R14, [R14, #NVRamPageSize]
        |
        LDRB	R14, NVPageSize
        ]
        MOV     R5, #1
        MOV     R14, R5, LSL R14        ; R14 = (1<<pagesize)

        ADD     R5, R0, R4              ; R5 = physical start address
        ADD     R5, R5, R14
        SUB     R14, R14, #1
        BIC     R5, R5, R14             ; R5 = physical end of page with start address in
        SUB     R5, R5, R4              ; R5 = logical end of page with start address in

        CMP     R5, R3
        MOVLO   R3, R5                  ; adjust R3 to not cross page boundary
 ]

  [     CacheCMOSRAM
        CMP     R0, #&100               ; check it's a cacheable segment
        BHS     %FT15

  [ :LNOT: :DEF: TestHarness
        LDR     R14, =CMOSRAMCache
  |
        ADR     R14, i2cWorkSpace
  ]
        Push    "R3, R4"
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being written
        MOV     R5, R1                  ; remember R1
12      LDRB    R14, [R1], #1           ; update cache copy
        STRB    R14, [R4], #1
        CMP     R4, R3
        BLO     %BT12
        MOV     R1, R5                  ; restore R1, and continue to update real memory
        Pull    "R3, R4"
  ]
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck

        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
	BL	TXAck

        Pull    "R0-R2"
        SUB     R5, R3, R0              ; R5 = bytes being written
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
        Push    "R0,R2"
20
        LDRB    R0, [R1], #1
        ADD     R6, R6, R0              ; update checksum counter
        BL      TXAck
        SUBS    R5, R5, #1
        BNE     %BT20

	BL	Stop

        MOV     R4, R6

	Pull	"R0,R2,R3,R5,R6,PC",,^

Neil Turton's avatar
Neil Turton committed
750 751
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
752 753
;	Read - Read a byte of CMOS RAM specified by logical address
;	ReadStraight - Read a byte of CMOS RAM specified by physical address
Kevin Bracey's avatar
Kevin Bracey committed
754
;       ReadWithError - Read a byte of CMOS RAM specified by logical address, giving error if out of range
Neil Turton's avatar
Neil Turton committed
755
;
Neil Turton's avatar
Neil Turton committed
756
; in:	R0 = address in CMOS RAM
Neil Turton's avatar
Neil Turton committed
757
;
Kevin Bracey's avatar
Kevin Bracey committed
758
; out:	R0 = data (illegal address return 0, or error for ReadWithError)
Neil Turton's avatar
Neil Turton committed
759
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
760 761 762
;

ReadStraight ROUT
Neil Turton's avatar
Neil Turton committed
763 764
	Push	"R1,R2,R14"
	B	%FT10
Neil Turton's avatar
Neil Turton committed
765

Kevin Bracey's avatar
Kevin Bracey committed
766 767 768 769 770 771 772 773 774 775 776 777 778
ReadWithError
        Push    "R1,R2,R14"
        BL      MangleCMOSAddress
        BCC     %FT10
        ADR     R0, ErrorBlock_CoreNotReadable
 [ International
        BL      TranslateError
 ]
        Pull    "R1,R2,R14"
        ORRS    PC, LR, #V_bit

        MakeErrorBlock CoreNotReadable

Neil Turton's avatar
Neil Turton committed
779
Read
Neil Turton's avatar
Neil Turton committed
780 781 782 783
	Push	"R1,R2,R14"
	BL	MangleCMOSAddress
	MOVCS	R0, #0			; pretend illegal addresses contain 0
	Pull	"R1,R2,PC", CS
Neil Turton's avatar
Neil Turton committed
784
10
Neil Turton's avatar
Neil Turton committed
785 786 787
  [	CacheCMOSRAM
	TEQ	R0, #&40		; is it Econet station number
	BEQ	%FT15	 		; if so then don't use cache
Kevin Bracey's avatar
Kevin Bracey committed
788 789 790 791 792
	CMP	R0, #&100		; check small cache limit
  [ :LNOT: :DEF: TestHarness
	LDRCC	R2, =CMOSRAMCache	; if in range
  |
	ADRCC	R2, i2cWorkSpace
Neil Turton's avatar
Neil Turton committed
793
  ]
Kevin Bracey's avatar
Kevin Bracey committed
794 795
	LDRCCB	R0, [R2, R0]		; read from cache
	Pull	"R1,R2,PC", CC		; and exit
Neil Turton's avatar
Neil Turton committed
796 797 798
15

; else drop thru into real CMOS reading code
Neil Turton's avatar
Neil Turton committed
799
  ]
Neil Turton's avatar
Neil Turton committed
800

Neil Turton's avatar
Neil Turton committed
801 802 803 804 805
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]
Neil Turton's avatar
Neil Turton committed
806

Neil Turton's avatar
Neil Turton committed
807 808 809
	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
810

Kevin Bracey's avatar
Kevin Bracey committed
811 812 813 814 815
        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
Neil Turton's avatar
Neil Turton committed
816
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
817

Neil Turton's avatar
Neil Turton committed
818
	BL	Start
Neil Turton's avatar
Neil Turton committed
819

Neil Turton's avatar
Neil Turton committed
820 821
	ADD	R0, R1, #1		; device address for read
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
822

Neil Turton's avatar
Neil Turton committed
823 824
	BL	RXByte			; returned in R0
	MOV	R2, R0			; copy to R2 for now
Neil Turton's avatar
Neil Turton committed
825

Neil Turton's avatar
Neil Turton committed
826 827
	MOV	R0, #1
	BL	ClockData
Neil Turton's avatar
Neil Turton committed
828

Neil Turton's avatar
Neil Turton committed
829
	BL	Stop
Neil Turton's avatar
Neil Turton committed
830

Neil Turton's avatar
Neil Turton committed
831
	MOV	R0, R2			; return the result
Neil Turton's avatar
Neil Turton committed
832

Neil Turton's avatar
Neil Turton committed
833
	Pull	"R1,R2,PC"
Neil Turton's avatar
Neil Turton committed
834

Kevin Bracey's avatar
Kevin Bracey committed
835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140

; *****************************************************************************
;
;       ReadBlock - Read a block of CMOS RAM specified by logical address
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy to
;       R2 = length
;
; out:  All registers preserved
;


ReadBlock ROUT
        Push    "R0-R3,R14"
  [     E2ROMSupport
        [ :LNOT: :DEF: TestHarness
        MOV	R14, #0
        LDRB	R14, [R14, #NVRamSize]
        |
        LDRB	R14, NVSize
        ]
        MOV     R14, R14, LSL #8
  |
        MOV     R14, #240
  ]

        CMP     R0, R14
        BHS     %FT90

        ADDS    R3, R0, R2              ; R3 = end address - check unsigned overflow
        BCS     %FT90
        CMP     R3, R14
        BHI     %FT90

        TEQ     R2, #0
        BEQ     %FT80

10      BL      ReadSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10
80
        Pull    "R0-R3,PC"

90
        ADD     SP, SP, #4              ; junk stacked R0
        ADR     R0, ErrorBlock_CoreNotReadable
 [ International
        BL      TranslateError
 ]
95
        Pull    "R1-R3,LR"
        ORRS    PC, LR, #V_bit

; *****************************************************************************
;
;       ReadSubBlock - Read a block of CMOS RAM specified by logical address.
;                      Assumes the address is valid, and will only read as much
;                      as it can in a single IIC transaction.
;
; in:   R0 = address in CMOS RAM
;       R1 = address to copy to
;       R2 = length
;
; out:  R0-R2 updated to reflect the amount read.
;
ReadSubBlock ROUT
        Push    "R3-R5,R14"
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&F0                ; [C0..F0) -> [10..40) cached
        MOVLO   R3, #&F0
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100               ; [F0..100) -> [00..10) cached
        MOVLO   R3, #&100
        MOVLO   R4, #&00-&F0
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
; R3 = logical end of this transaction (exclusive)
  [     CacheCMOSRAM
        TEQ     R0, #0                  ; check it's a cacheable segment
        BEQ     %FT15
        CMP     R0, #&100
        BHS     %FT15

  [ :LNOT: :DEF: TestHarness
        LDR     R14, =CMOSRAMCache
  |
        ADR     R14, i2cWorkSpace
  ]
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being read
        ADD     R0, R0, R14             ; update return R0
        SUB     R2, R2, R14             ; update return R2

12      LDRB    R14, [R4], #1
        CMP     R4, R3
        STRB    R14, [R1], #1
        BLO     %BT12
        Pull    "R3-R5,PC",,^
  ]
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck

        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
	BL	TXAck

	BL	Start

	ADD	R0, R1, #1		; device address for read
	BL	TXAck

        Pull    "R0-R2"
        SUB     R5, R3, R0              ; R5 = bytes being read
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
        Push    "R0,R2"
20
        BL      RXByte
        STRB    R0, [R1], #1
        SUBS    R5, R5, #1
        MOVNE   R0, #0                  ; not done - ACK byte
	MOVEQ   R0, #1                  ; done - no ACK
	BL	ClockData
        BNE     %BT20

	BL	Stop

	Pull	"R0,R2,R3-R5,PC",,^

; *****************************************************************************
;
;       ChecksumBlock - Checksum a block of CMOS RAM specified by logical address
;                       Assumes the address is valid.
;
; in:   R0 = address in CMOS RAM
;       R1 = initial checksum
;       R2 = length
;
; out:  R1 incremented by sum of bytes in range
;


ChecksumBlock ROUT
        Push    "R0,R2,R14"

10      BL      ChecksumSubBlock
        BVS     %FT80
        TEQ     R2, #0
        BNE     %BT10
80
        Pull    "R0,R2,PC"


; *****************************************************************************
;
;       ChecksumSubBlock - Checksum a block of CMOS RAM specified by logical address.
;                          Assumes the address is valid, and will only read as much
;                          as it can in a single IIC transaction. Skips over
;                          239 (the checksum byte itself), and 240-255 (OTP area).
;
; in:   R0 = address in CMOS RAM
;       R1 = initial checksum
;       R2 = length
;
; out:  R0-R2 updated to reflect the data read.
;
ChecksumSubBlock ROUT
        Push    "R3-R5,R14"
; establish end of the current contiguous block, and the logical->physical address offset.
        CMP     R0, #1                  ; 00 -> 40 uncached
        MOVLO   R3, #1
        MOVLO   R4, #&40-&00
        BLO     %FT10
        CMP     R0, #&C0                ; [01..C0) -> [41..100) cached
        MOVLO   R3, #&C0
        MOVLO   R4, #&41-&01
        BLO     %FT10
        CMP     R0, #&EF                ; [C0..EF) -> [10..3F) cached
        MOVLO   R3, #&EF
        MOVLO   R4, #&10-&C0
        BLO     %FT10
        CMP     R0, #&100
        ADDHS   R3, R0, R2              ; [100..) -> [100..) uncached
        MOVHS   R4, #0
        BHS     %FT10

;  [EF..100) -> not checksummed
        MOV     R3, #&100
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
        SUB     R14, R3, R0
        ADD     R0, R0, R14
        SUB     R2, R2, R14
        Pull    "R3-R5,PC"


; R3 = logical end of current segment (exclusive)
; R4 = offset from logical to physical address for this segment
10
        ADD     R14, R0, R2
        CMP     R3, R14
        MOVHI   R3, R14
; R3 = logical end of this transaction (exclusive)

  [     CacheCMOSRAM
        TEQ     R0, #0                  ; check it's a cacheable segment
        BEQ     %FT15
        CMP     R0, #&100
        BHS     %FT15

  [ :LNOT: :DEF: TestHarness
        LDR     R14, =CMOSRAMCache
  |
        ADR     R14, i2cWorkSpace
  ]
        ADD     R3, R3, R4              ; R3 = physical end address
        ADD     R4, R4, R0              ; R4 = physical address
        ADD     R3, R3, R14             ; R3 = cache end address
        ADD     R4, R4, R14             ; R4 = cache address
        SUB     R14, R3, R4             ; R14 = bytes being read
        ADD     R0, R0, R14             ; update return R0
        SUB     R2, R2, R14             ; update return R2

12      LDRB    R14, [R4], #1
        CMP     R4, R3
        ADD     R1, R1, R14
        BLO     %BT12
        Pull    "R3-R5,PC"
  ]
15
        Push    "R0-R2"
        ADD     R0, R0, R4              ; R0 = physical address
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]

	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck

        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; offset (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; offset (LSB)
	BL	TXAck

	BL	Start

	ADD	R0, R1, #1		; device address for read
	BL	TXAck

        Pull    "R0-R2"
        SUB     R5, R3, R0              ; R5 = bytes being read
        ADD     R0, R0, R5              ; update return R0
        SUB     R2, R2, R5              ; update return R2
        Push    "R0,R2"
20
        BL      RXByte
        ADD     R1, R1, R0
        SUBS    R5, R5, #1
        MOVNE   R0, #0                  ; not done - ACK byte
	MOVEQ   R0, #1                  ; done - no ACK
	BL	ClockData
        BNE     %BT20

	BL	Stop

	Pull	"R0,R2,R3-R5,PC"

Neil Turton's avatar
Neil Turton committed
1141 1142
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1143 1144
;	GetI2CAddress - Convert NVRam physical address to i2c device address
;	                and offset
Neil Turton's avatar
Neil Turton committed
1145
;
Neil Turton's avatar
Neil Turton committed
1146
; in:	R0 = NVRam physical address (&00..size of NVRam)
Neil Turton's avatar
Neil Turton committed
1147
;
Neil Turton's avatar
Neil Turton committed
1148
; out:	R0 preserved
Neil Turton's avatar
Neil Turton committed
1149
;
Neil Turton's avatar
Neil Turton committed
1150 1151 1152
;	C=0 => NVRam address is valid
;	 R0 = physical address within i2c device
;	 R1 = i2c device address for writing. Increment this device address
Kevin Bracey's avatar
Kevin Bracey committed
1153
;	      by 1 for reading. Bit 8 is set if device requires 2-byte physical address.
Neil Turton's avatar
Neil Turton committed
1154
;
Neil Turton's avatar
Neil Turton committed
1155 1156 1157 1158 1159 1160
;	C=1 => NVRam address is out of range of CMOS or E2ROM chips
;	 R0 preserved
;	 R1 preserved

  [	E2ROMSupport
GetI2CAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170
	Push	"R14"
	[ :LNOT: :DEF: TestHarness
	MOV	R14, #0			; get no 256 byte blocks and calculate end address
	LDRB	R14, [R14, #NVRamSize]
	|
	LDRB	R14, NVSize
	]
	MOV	R14, R14, LSL #8
	CMP	R0, R14
	Pull	"R14",CS
Neil Turton's avatar
Neil Turton committed
1171 1172
	ORRCSS	PC, R14, #C_bit		; indicate invalid

Kevin Bracey's avatar
Kevin Bracey committed
1173 1174 1175
; address is < end address -> is valid
	[ :LNOT: :DEF: TestHarness
	MOV	R1, #0
Neil Turton's avatar
Neil Turton committed
1176
	LDRB	R1, [R1, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
	|
	LDRB	R1, RTCFlag
	]
	TEQ	R1, #0
	MOVNE	R1, #RTCAddress
	[ :LNOT: :DEF: TestHarness
	LDREQB  R1, [R1, #NVRamBase]
	|
	LDREQB  R1, NVBase
	]

        CMP     R14, #2*1024            ; is the device bigger than 2K? If so, new addressing scheme
        ORRHI   R1, R1, #&100           ; set magic bit => 2 byte address
        BHI     %FT50
Neil Turton's avatar
Neil Turton committed
1191

Kevin Bracey's avatar
Kevin Bracey committed
1192 1193 1194 1195 1196
	MOVS	R14, R0, LSR #8		; put top bits of physical address into device address
	ORRNE	R1, R1, R14, LSL #1
	ANDNE	R0, R0, #&FF		; and use address within 256 byte block
50
	Pull	"R14"
Neil Turton's avatar
Neil Turton committed
1197
	BICS	PC, R14, #C_bit		; indicate valid
Kevin Bracey's avatar
Kevin Bracey committed
1198

Neil Turton's avatar
Neil Turton committed
1199
  ]
Neil Turton's avatar
Neil Turton committed
1200 1201 1202


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
1203 1204 1205 1206 1207
;
;	MangleCMOSAddress - Convert from logical to physical address
;
;	Doesn't check if address is larger than the amount of NVRam installed
;
Kevin Bracey's avatar
Kevin Bracey committed
1208
; in:	R0 = logical address (&00...)
Neil Turton's avatar
Neil Turton committed
1209
;
Kevin Bracey's avatar
Kevin Bracey committed
1210 1211
; out:	C=0 => valid logical address
;	 R0 = physical address (&40..&FF,&10..&3F,&00..0F,&100..)
Neil Turton's avatar
Neil Turton committed
1212
;
Kevin Bracey's avatar
Kevin Bracey committed
1213
;	C=1 => invalid logical address
Neil Turton's avatar
Neil Turton committed
1214 1215
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
1216

Neil Turton's avatar
Neil Turton committed
1217
MangleCMOSAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
 [ E2ROMSupport
	Push	"R14"
	[ :LNOT: :DEF: TestHarness
	MOV	R14, #0			; read no 256 byte blocks and calculate end address
	LDRB	R14, [R14, #NVRamSize]
	|
	LDRB	R14, NVSize
	]
	MOV	R14, R14, LSL #8
	CMP	R0, R14			; if >= end address then
	Pull	"R14"
	ORRCSS	PC, R14, #C_bit		;    invalid

	CMP	R0, #&100		; if < end address && >= &100 then
	BICCSS	PC, R14, #C_bit		;    valid (no mungeing)
 ]

	CMP	R0, #&F0		; if < &100 && >= &f0 then
        [ E2ROMSupport
        SUBCS   R0, R0, #&F0            ;    map &F0->&FF to &00->0F for OTP section
        BICCSS  PC, R14, #C_bit
        |
	ORRCSS	PC, R14, #C_bit		;    invalid
        ]
Neil Turton's avatar
Neil Turton committed
1242

Neil Turton's avatar
Neil Turton committed
1243 1244 1245
	ADD	R0, R0, #&40		; now in range &40..&13F
	CMP	R0, #&100
	SUBCS	R0, R0, #(&100-&10)	; now in range &40..&FF, &10..&3F
Kevin Bracey's avatar
Kevin Bracey committed
1246
	BICS	PC, R14, #C_bit		; valid
Neil Turton's avatar
Neil Turton committed
1247 1248 1249

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1250 1251
;	ValChecksum - test to see if the CMOS checksum is OK
;
Kevin Bracey's avatar
Kevin Bracey committed
1252 1253 1254 1255 1256
;       This routine performs MangleCMOSAddress inherently.
;
;       The checksum does not include physical locations &00->&0F, even
;       if they are OTP section (as this is usually used for a unique id
;       which will be different for every machine and can't be changed).
Neil Turton's avatar
Neil Turton committed
1257
;
Neil Turton's avatar
Neil Turton committed
1258
; in:	none
Neil Turton's avatar
Neil Turton committed
1259
;
Neil Turton's avatar
Neil Turton committed
1260 1261 1262
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1263 1264
;

Neil Turton's avatar
Neil Turton committed
1265
  [ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1266

Kevin Bracey's avatar
Kevin Bracey committed
1267
ValChecksum	ENTRY "R1-R2"
Neil Turton's avatar
Neil Turton committed
1268

Kevin Bracey's avatar
Kevin Bracey committed
1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
        MOV     R0, #0
        MOV     R1, #CMOSxseed
	[ :LNOT: :DEF: TestHarness
	MOV	R2, #0			; read number of 256 byte blocks and calculate end address
	LDRB	R2, [R2, #NVRamSize]
	|
	LDRB	R2, NVSize
	]
	MOV	R2, R2, LSL #8
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1279 1280

;
Kevin Bracey's avatar
Kevin Bracey committed
1281
; R1 contains the actual checksum. Compare it with the recorded checksum
Neil Turton's avatar
Neil Turton committed
1282
;
Kevin Bracey's avatar
Kevin Bracey committed
1283 1284 1285
40
	MOV	R0, #CheckSumCMOS
	BL	Read
Neil Turton's avatar
Neil Turton committed
1286
	AND	R2, R0, #&FF		; value from checksum location
Kevin Bracey's avatar
Kevin Bracey committed
1287
	AND	R0, R1, #&FF		; calculated value into R0
Neil Turton's avatar
Neil Turton committed
1288
	CMPS	R0, R2
Neil Turton's avatar
Neil Turton committed
1289

Neil Turton's avatar
Neil Turton committed
1290 1291
	EXIT
  ]
Neil Turton's avatar
Neil Turton committed
1292 1293 1294

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1295
;	MakeChecksum - calculate and write a correct checksum
Neil Turton's avatar
Neil Turton committed
1296
;
Neil Turton's avatar
Neil Turton committed
1297
; in:	none
Neil Turton's avatar
Neil Turton committed
1298
;
Neil Turton's avatar
Neil Turton committed
1299 1300
; out:	R0 = calculated checksum
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1301 1302
;

Neil Turton's avatar
Neil Turton committed
1303
	[ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1304

Neil Turton's avatar
Neil Turton committed
1305
MakeChecksum	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
	Push	"R1-R2,R14"
        MOV     R0, #0
        MOV     R1, #CMOSxseed
	[ :LNOT: :DEF: TestHarness
	MOV	R2, #0
	LDRB	R2, [R2, #NVRamSize]
	|
	LDRB	R2, NVSize
	]
	MOV	R2, R2, LSL #8
        BL      ChecksumBlock
Neil Turton's avatar
Neil Turton committed
1317 1318
	MOV	R0, #CheckSumCMOS
	BL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1319
	Pull	"R1-R2,PC"
Neil Turton's avatar
Neil Turton committed
1320
	]
Neil Turton's avatar
Neil Turton committed
1321

Kevin Bracey's avatar
Kevin Bracey committed
1322 1323
        LTORG

Neil Turton's avatar
Neil Turton committed
1324 1325
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1326
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
1327
;
Neil Turton's avatar
Neil Turton committed
1328 1329 1330 1331 1332 1333 1334 1335 1336
; in:	UTC time:
;	R0 = hours
;	R1 = minutes
;	R2 = day of month
;	R3 = month
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1337
;
Neil Turton's avatar
Neil Turton committed
1338
;	Any of the above, if -1, will not be written to
Neil Turton's avatar
Neil Turton committed
1339 1340 1341
;

SetTime ROUT
Neil Turton's avatar
Neil Turton committed
1342
	Push	"R4, R14"		; save registers
Neil Turton's avatar
Neil Turton committed
1343

Kevin Bracey's avatar
Kevin Bracey committed
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
	[ :LNOT: :DEF: TestHarness
	MOV	R14, #0
	LDRB	R14, [R14, #RTCFitted]
	|
	LDRB	R14, RTCFlag
	]

        TEQ     R14, #0
        BNE     %FT20

; no RTC - just set soft copy

 [ :LNOT: :DEF: TestHarness
        BL      RegToRealTime
 ]
        Pull    "R4, PC"

20
Neil Turton's avatar
Neil Turton committed
1362 1363
; write year to CMOS RAM

Neil Turton's avatar
Neil Turton committed
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398
	MOV	R4, R0			; save hours in R4

	Push	"R1"
	MOVS	R1, R5
	MOVPL	R0, #YearCMOS
	BLPL	Write
	MOVS	R1, R6
	MOVPL	R0, #YearCMOS+1
	BLPL	Write

	CMP	R4, #-1			; are we writing time ?
	Pull	"R1",EQ			; [no, then skip]
	BEQ	%FT30

	MOV	R0, #&01		; start at address 1
    [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
	Pull	"R1"
	BL	StartTXPollAck
	MOV	R0, #&01		; offset 1
	BL	TXAck
	MOV	R0, R8			; centiseconds
	BL	HTBTA
	MOV	R0, R7			; seconds
	BL	HTBTA
	MOV	R0, R1			; minutes
	BL	HTBTA
	MOV	R0, R4			; hours
	BL	HTBTA
	BL	Stop

Neil Turton's avatar
Neil Turton committed
1399
30
Neil Turton's avatar
Neil Turton committed
1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419
	CMP	R2, #-1			; are we writing date ?
	BEQ	%FT40			; [no, then skip]

	MOV	R0, #&05		; start at address 5
    [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
	BL	StartTXPollAck
	MOV	R0, #&05		; offset 5
	BL	TXAck
	MOV	R0, R2			; day of month
	BL	HexToBCD
	ORR	R0, R0, R5, LSL #6	; year in bits 6,7; day in bits 0..5
	BL	TXAck
	MOV	R0, R3			; months
	BL	HTBTA
	BL	Stop
Neil Turton's avatar
Neil Turton committed
1420

Neil Turton's avatar
Neil Turton committed
1421 1422 1423 1424 1425 1426
40
	MOV	R0, R4			; put hours back in R0
  [ :LNOT: :DEF: TestHarness
	BL	RTCToRealTime
  ]
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1427 1428 1429

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1430
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
1431
;
Neil Turton's avatar
Neil Turton committed
1432
; in:	-
Neil Turton's avatar
Neil Turton committed
1433
;
Neil Turton's avatar
Neil Turton committed
1434 1435 1436 1437 1438 1439 1440 1441
; out:	R0 = hours
;	R1 = minutes
;	R2 = days
;	R3 = months
;	R5 = year (lo)
;	R6 = year (hi)
;	R7 = seconds
;	R8 = centiseconds
Neil Turton's avatar
Neil Turton committed
1442 1443 1444
;

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495
	Push	"R4, R14"

	MOV	R0, #&01		; start at address 1
    [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R0, R1			; write address
    |
	MOV	R0, #RTCAddress
    ]
	BL	StartTXPollAck
	MOV	R0, #&01		; offset 1
	BL	TXAck
	BL	Start
    [	E2ROMSupport
	ADD	R0, R1, #1		; read address
    |
	MOV	R0, #(RTCAddress+1)	; read address
    ]
	BL	TXAck
	BL	RXByte
	BL	BCDToHex
	MOV	R8, R0			; centiseconds
	BL	CD0RBTH
	MOV	R7, R0			; seconds
	BL	CD0RBTH
	MOV	R1, R0			; minutes
	BL	CD0RBTH
	MOV	R4, R0			; hours
	BL	ClockData0
	BL	RXByte
	AND	R0, R0, #&3F		; day of month (clear year bits)
	BL	BCDToHex
	MOV	R2, R0
	BL	ClockData0
	BL	RXByte
	AND	R0, R0, #&1F		; month (clear day of week bits)
	BL	BCDToHex
	MOV	R3, R0
	MOV	R0, #1
	BL	ClockData
	BL	Stop

	MOV	R0, #YearCMOS
	BL	Read
	MOV	R5, R0			; year (lo)

	MOV	R0, #YearCMOS+1
	BL	Read
	MOV	R6, R0			; year (hi)

	MOV	R0, R4			; put hours in R0
Neil Turton's avatar
Neil Turton committed
1496 1497

; Ensure day/month are non-zero, fixes RTCToRealTime
Neil Turton's avatar
Neil Turton committed
1498 1499 1500 1501 1502
 [ {TRUE}				; LRust, fix RP-0370
	TEQ	R2, #0			; Valid day?
	MOVEQ	R2, #1			; No then force 1st
	TEQ	R3, #0			; Invalid month?
	MOVEQ	R3, #1			; Yes then force Jan
Neil Turton's avatar
Neil Turton committed
1503
 ]
Neil Turton's avatar
Neil Turton committed
1504
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1505 1506 1507

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1508 1509 1510 1511
;	InitCMOSCache - Initialise cache of CMOS RAM

  [	CacheCMOSRAM

1512
InitCMOSCache	ENTRY "r0-r6"
Neil Turton's avatar
Neil Turton committed
1513 1514
    [	E2ROMSupport

Kevin Bracey's avatar
Kevin Bracey committed
1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
; Need to set the slowest speed so we can probe

        MOV     R2, #0
      [ ClockNVMemoryFast
        MOV     R3, #10         ; Default speed setting (5s delays)
	[ :LNOT: :DEF: TestHarness
        STRB    R3, [R2, #NVRamSpeed]
	|
        STRB    R3, NVSpeed
	]
      ]

;	First determine what hardware we've got fitted, R4 holds the number of
Neil Turton's avatar
Neil Turton committed
1528 1529 1530 1531 1532
;	256 byte blocks that we've found

	; Have we got an RTC ?
	MOV	R0, #RTCAddress
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1533 1534 1535 1536 1537 1538 1539 1540
	MOVVS	R4, #0
	MOVVC	R4, #1
	[ :LNOT: :DEF: TestHarness
	STRB	R4, [R2, #RTCFitted]
	|
	STRB	R4, RTCFlag
	]
        MOV     R5, #4          ; assume 16 byte page size to start with
1541
        MOV     R6, #0          ; assume not protected
Kevin Bracey's avatar
Kevin Bracey committed
1542 1543 1544 1545 1546 1547 1548 1549 1550 1551

; Have we got a 2K E ?
        MOV     r1, #E2ROMAddress2K
	MOV	r0, #(E2ROMAddress2K+14)
	BL	DummyAccess
	MOVVC	R4, #8
      [ ClockNVMemoryFast
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
      ]
	BVC	%FT5
Neil Turton's avatar
Neil Turton committed
1552 1553

; Have we got a 1K E ?
Kevin Bracey's avatar
Kevin Bracey committed
1554
        MOV     r1, #E2ROMAddress
Neil Turton's avatar
Neil Turton committed
1555 1556
	MOV	r0, #(E2ROMAddress+6)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1557
	MOVVC	R4, #4
Neil Turton's avatar
Neil Turton committed
1558 1559 1560 1561 1562
	BVC	%FT5

; Have we got 512 bytes of E ?
	MOV	r0, #(E2ROMAddress+2)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1563
	MOVVC	R4, #2
Neil Turton's avatar
Neil Turton committed
1564 1565
	BVC	%FT5

Kevin Bracey's avatar
Kevin Bracey committed
1566 1567 1568
; Have we got a 16K device ? (Note that this probe would make a 24C08 device respond -
; but if we've gotten this far it would have to be a < 512 byte version; we've never
; used such a device).
Neil Turton's avatar
Neil Turton committed
1569

Kevin Bracey's avatar
Kevin Bracey committed
1570 1571 1572 1573 1574 1575 1576 1577
        MOV     r1, #E2ROMAddress16K
	MOV	r0, #E2ROMAddress16K
	BL	DummyAccess
	MOVVC	R4, #64
        MOVVC   R5, #6          ; 64 byte page size
      [ ClockNVMemoryFast
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
      ]
1578 1579
        BVC     %FT5

1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
; Have we got a 4K device?

        MOV     r1, #E2ROMAddress4K
	MOV	r0, #E2ROMAddress4K
	BL	DummyAccess
	MOVVC	R4, #16
        MOVVC   R6, #12         ; Only bottom 3K writable
        MOVVC   R5, #5          ; 32 byte page size
      [ ClockNVMemoryFast
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
      ]
        BVC     %FT5

1593 1594 1595 1596 1597 1598
; Have we got an 8K device?

        MOV     r1, #E2ROMAddress8K
	MOV	r0, #E2ROMAddress8K
	BL	DummyAccess
	MOVVC	R4, #32
1599
        MOVVC   R6, #24         ; Only bottom 6K writable
1600 1601 1602 1603 1604
        MOVVC   R5, #5          ; 32 byte page size
      [ ClockNVMemoryFast
        MOVVC   R3, #3          ; Fast speed setting (1.5s delays)
      ]

Kevin Bracey's avatar
Kevin Bracey committed
1605 1606 1607 1608
	MOVVS   R1, #RTCAddress
        MOVVS   R5, #8          ; 256 byte page size for CMOS

5
Neil Turton's avatar
Neil Turton committed
1609
	; Set the NVRam count
Kevin Bracey's avatar
Kevin Bracey committed
1610 1611 1612 1613
	[ :LNOT: :DEF: TestHarness
	STRB    R1, [R2, #NVRamBase]
	STRB	R4, [R2, #NVRamSize]
        STRB    R5, [R2, #NVRamPageSize]
1614 1615 1616
        TEQ     R6, #0
        MOVEQ   R6, R4
        STRB    R6, [R2, #NVRamWriteSize]
Kevin Bracey's avatar
Kevin Bracey committed
1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629
      [ ClockNVMemoryFast
        STRB    R3, [R2, #NVRamSpeed]
      ]
	LDR	R3, =CMOSRAMCache
	|
	STRB    R1, NVBase
	STRB	R4, NVSize
        STRB    R5, NVPageSize
      [ ClockNVMemoryFast
        STRB    R3, NVSpeed
      ]
	ADR	R3, i2cWorkSpace
	]
Neil Turton's avatar
Neil Turton committed
1630 1631

	; Initialise the cache
Kevin Bracey's avatar
Kevin Bracey committed
1632 1633 1634 1635 1636 1637 1638 1639 1640
        TEQ     R4, #8                  ; check for 2K part
	MOVNE	r0, #&00		; if not, then start at 0 anyway and read non-OTP data into location 0..15
        BNE     %FT07
	BL	ReadOTPArea
	MOV	r0, #&10		; read rest of it from 16 onwards
07
        BL      GetI2CAddress           ; and convert to device address and offset
        MOV     R2, R0                  ; save the offset
        MOV     R4, #&100               ; stop at &100
Neil Turton's avatar
Neil Turton committed
1641 1642 1643
    |
	MOV	R1, #RTCAddress
	MOV	R2, #&10
Kevin Bracey's avatar
Kevin Bracey committed
1644 1645 1646 1647 1648 1649
	MOV	R4, #&100		; stop at address &100
        [	:LNOT: :DEF: TestHarness
	LDR	R3, =CMOSRAMCache
        |
	ADR	R3, i2cWorkSpace
        ]
Neil Turton's avatar
Neil Turton committed
1650
    ]
Kevin Bracey's avatar
Kevin Bracey committed
1651
09
Neil Turton's avatar
Neil Turton committed
1652
	BL	Start
Neil Turton's avatar
Neil Turton committed
1653

Neil Turton's avatar
Neil Turton committed
1654 1655
	MOV	R0, R1			; write address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1656

Kevin Bracey's avatar
Kevin Bracey committed
1657 1658 1659 1660 1661
        TST     R1, #&100               ; 2-byte address?
        MOVNE   R0, R2, LSR #8          ; memory word address (MSB)
        BLNE    TXAck

	AND	R0, R2, #&FF		; memory word address (LSB)
Neil Turton's avatar
Neil Turton committed
1662
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1663

Neil Turton's avatar
Neil Turton committed
1664
	BL	Start
Neil Turton's avatar
Neil Turton committed
1665

Kevin Bracey's avatar
Kevin Bracey committed
1666
	ORR	R0, R1, #1		; read address
Neil Turton's avatar
Neil Turton committed
1667
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1668 1669

10
Neil Turton's avatar
Neil Turton committed
1670 1671 1672
	BL	RXByte			; returned in R0
	STRB	R0, [R3, R2]
	ADD	R2, R2, #1		; increment R2 to phys. address
Kevin Bracey's avatar
Kevin Bracey committed
1673 1674
	CMP	R2, R4			; stop when we hit end address
	BGE	%FT20
Neil Turton's avatar
Neil Turton committed
1675

Kevin Bracey's avatar
Kevin Bracey committed
1676 1677 1678
	TST	R2, #&FF		; still in same 256 byte block?
	MOVNE	R0, #0			; yes => not done .. ACK that byte
	MOVEQ	R0, #1			; no => finish off reading block
Neil Turton's avatar
Neil Turton committed
1679
	BL	ClockData
Kevin Bracey's avatar
Kevin Bracey committed
1680 1681 1682 1683 1684 1685 1686 1687
	BNE	%BT10			; yes => continue reading

   [ E2ROMSupport
	BL	Stop
	MOV	R0, R2			; in next 256 byte block so get device + address
	BL	GetI2CAddress
	B	%BT09			; and start next block
   ]
Neil Turton's avatar
Neil Turton committed
1688
20
Neil Turton's avatar
Neil Turton committed
1689 1690 1691
	MOV	R0, #1			; finish off reading block
	BL	ClockData
	BL	Stop
Kevin Bracey's avatar
Kevin Bracey committed
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726

   [ E2ROMSupport
        TEQ     R4, #&100               ; have we reached the end?
        EXIT    EQ                      ; exit if so

        MOV     R0, R4                  ; start next block from R4
        MOV     R4, #&100               ; stop at &100
        BL      GetI2CAddress           ; convert to device address and offset
        MOV     R2, R0                  ; save the offset
        B       %BT09                   ; and go round again
   |
	EXIT
   ]

   [ E2ROMSupport
ReadOTPArea Entry
	BL	Start
	MOV	r0, #E2ROMAddress2K_OTP
	BL	TXAck
	MOV	r0, #0				; OTP memory word address
	BL	TXAck
	BL	Start
	MOV	r0, #E2ROMAddress2K_OTP + 1	; switch to read
	BL	TXAck
	MOV	r2, #0
10
	BL	RXByte
	STRB	r0, [r3, r2]
	ADD	r2, r2, #1
	TEQ	r2, #16
	MOVNE	r0, #0				; not done, so clock zero
	MOVEQ	r0, #1
	BL	ClockData
	BNE	%BT10
	BL	Stop
Neil Turton's avatar
Neil Turton committed
1727
	EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1728
   ]
Neil Turton's avatar
Neil Turton committed
1729

Neil Turton's avatar
Neil Turton committed
1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754
  ]


; *****************************************************************************
;
;	DummyAccess - do a dummy access of the specified device to find out
;	              if it is present
;
; in:	R0 = Write address of device
;
; out:	All registers preserved
;	V=0 => device is present
;	V=1 => device is not present

; Have we got an RTC ? do a read from location 0 to find out

  [ E2ROMSupport
DummyAccess	ENTRY

	BL	Start
	BL	TXAck			; do write and set V if no ack
	BL	Stop			; Doesn't change the PSR
	EXIT				; Exit with V set appropriately
  ]

Kevin Bracey's avatar
Kevin Bracey committed
1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895
; *****************************************************************************
;
;       SWI OS_NVMemory
;
; in:   R0 = reason code
;

NVMemorySWI     ENTRY
        BL      NVMemorySub
        PullEnv
        ORRVS   LR, LR, #V_bit
        ExitSWIHandler

NVMemorySub
        CMP     R0, #4
        ADDLS   PC, PC, R0, LSL #2
        B       NVMemory_Unknown
        B       NVMemory_Size
        B       NVMemory_Read
        B       NVMemory_Write
        B       NVMemory_ReadBlock
        B       NVMemory_WriteBlock

NVMemory_Unknown
        ADRL    R0, ErrorBlock_HeapBadReason
 [ International
        Push    LR
        BL      TranslateError
        Pull    LR
 ]
        ORRS    PC, LR, #V_bit

; -----------------------------------------------------------------------------
; OS_NVMemory 0 - find NV memory size
;
; in:   R0 = 0
;
; out:  R1 = NV memory size in bytes
;
NVMemory_Size
  [     E2ROMSupport
        LDRB    R1, [R0, #NVRamSize]
        MOV     R1, R1, LSL #8
  |
        MOV     R1, #240
  ]
        MOVS    PC, LR

; -----------------------------------------------------------------------------
; OS_NVMemory 1 - read a byte
;
; in:   R0 = 1
;       R1 = location
;
; out:  R2 = value
;
NVMemory_Read
        ENTRY   "R4"
        MOV     R4, PC
        TEQP    PC, #SVC_mode   ; enable interrupts - this may take some time
        MOV     R0, R1
        BL      ReadWithError
        MOVVC   R2, R0
        MOVVC   R0, #1          ; must preserve R0
        ORRVS   R4, R4, #V_bit
        TEQP    PC, R4          ; restore interrupt state
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 2 - write a byte
;
; in:   R0 = 1
;       R1 = location
;       R2 = value
;
NVMemory_Write ROUT
        [ ProtectStationID
        TEQ     R1, #0          ; just ignore writes to byte 0
        MOVEQ   PC, R14
        ]
        ENTRY   "R1,R4"
        MOV     R4, PC
        TEQP    PC, #SVC_mode   ; enable interrupts - this may take some time
        MOV     R0, R1
        MOV     R1, R2
        BL      WriteWithError
        MOVVC   R0, #2          ; must preserve R0
        ORRVS   R4, R4, #V_bit
        TEQP    PC, R4          ; restore interrupt state
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 3 - read a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_ReadBlock
        ENTRY   "R1-R4"
        MOV     R4, PC
        TEQP    PC, #SVC_mode   ; enable interrupts - this may take some time
        MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      ReadBlock
        MOVVC   R0, #3          ; must preserve R0
        ORRVS   R4, R4, #V_bit
        TEQP    PC, R4          ; restore interrupt state
        EXIT

; -----------------------------------------------------------------------------
; OS_NVMemory 4 - write a block
;
; in:   R0 = 3
;       R1 = location
;       R2 = buffer
;       R3 = length
;
NVMemory_WriteBlock ROUT
        ENTRY   "R1-R4"
        MOV     R4, PC
        TEQP    PC, #SVC_mode   ; enable interrupts - this may take some time
        [ ProtectStationID
        TEQ     R1, #0
        BNE     %FT10
        ADD     R1, R1, #1
        ADD     R2, R2, #1
        TEQ     R3, #0
        SUBNE   R3, R3, #1      ; steer clear of station ID
        ]
10      MOV     R0, R1
        MOV     R1, R2
        MOV     R2, R3
        BL      WriteBlock
        MOVVC   R0, #4          ; must preserve R0
        ORRVS   R4, R4, #V_bit
        TEQP    PC, R4          ; restore interrupt state
        EXIT

Neil Turton's avatar
Neil Turton committed
1896
	END