i2cutils 44 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.
Neil Turton's avatar
Neil Turton committed
37 38 39

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

Kevin Bracey's avatar
Kevin Bracey committed
40 41
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
42 43

; Device addresses
Kevin Bracey's avatar
Kevin Bracey committed
44
RTCAddress		*	&a0     ; traditional RTC / 240 byte CMOS
Neil Turton's avatar
Neil Turton committed
45
  [	E2ROMSupport
Kevin Bracey's avatar
Kevin Bracey committed
46 47 48 49
E2ROMAddress		*	&a8     ; 24C08 device - 512 byte or 1K
E2ROMAddress2K		*	&e0     ; 24C174 device - 2K
E2ROMAddress2K_OTP	*	&60     ; 24C174 device - OTP section
E2ROMAddress16K         *       &a8     ; 24C128 device - 16K
Neil Turton's avatar
Neil Turton committed
50 51
  ]

Neil Turton's avatar
Neil Turton committed
52 53
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
54
;	HexToBCD - Convert byte in hex to BCD
Neil Turton's avatar
Neil Turton committed
55
;
Neil Turton's avatar
Neil Turton committed
56
; in:	R0 = byte in hex
Neil Turton's avatar
Neil Turton committed
57
;
Neil Turton's avatar
Neil Turton committed
58 59
; 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
60 61 62
;

HexToBCD ROUT
Neil Turton's avatar
Neil Turton committed
63 64 65 66 67
	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
68 69 70

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

BCDToHex ROUT
Neil Turton's avatar
Neil Turton committed
80 81 82 83 84
	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
85 86 87

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
88
;	SetC1C0 - Set clock and data lines to values in R1 and R0 respectively
Neil Turton's avatar
Neil Turton committed
89
;
Neil Turton's avatar
Neil Turton committed
90
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
91 92 93
;

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

Neil Turton's avatar
Neil Turton committed
97 98 99 100 101 102 103 104 105 106 107
	[ 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
108

Neil Turton's avatar
Neil Turton committed
109 110
	MOV	R2, #IOC
	STRB	R0, [R2, #IOCControl]
Neil Turton's avatar
Neil Turton committed
111

Kevin Bracey's avatar
Kevin Bracey committed
112 113 114 115 116 117 118 119 120 121 122 123
 [ 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
124
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
125

Neil Turton's avatar
Neil Turton committed
126
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
127 128 129

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
130
;	DoMicroDelay - Delay for >= R0/2 microseconds
Neil Turton's avatar
Neil Turton committed
131
;
Neil Turton's avatar
Neil Turton committed
132 133 134
; 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
135
;
Neil Turton's avatar
Neil Turton committed
136
; out:	R0,R1 corrupted
Neil Turton's avatar
Neil Turton committed
137 138 139
;

DoMicroDelay ROUT
Neil Turton's avatar
Neil Turton committed
140
	Push	R14
Neil Turton's avatar
Neil Turton committed
141

Neil Turton's avatar
Neil Turton committed
142 143
	STRB	R0, [R2, #Timer0LR]	; copy counter into output latch
	LDRB	R1, [R2, #Timer0CL]	; R1 := low output latch
Neil Turton's avatar
Neil Turton committed
144
10
Neil Turton's avatar
Neil Turton committed
145 146 147 148 149 150 151
	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
152

Neil Turton's avatar
Neil Turton committed
153
	Pull	PC
Neil Turton's avatar
Neil Turton committed
154

Neil Turton's avatar
Neil Turton committed
155
	LTORG
Neil Turton's avatar
Neil Turton committed
156 157 158

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

ClockData ROUT
Neil Turton's avatar
Neil Turton committed
167
	Push	"R1, R14"
Neil Turton's avatar
Neil Turton committed
168

Neil Turton's avatar
Neil Turton committed
169 170
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
171 172 173 174 175

 [ {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
176 177 178
	MOV	R1,PC
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
179
 ]
Neil Turton's avatar
Neil Turton committed
180 181
	MOV	R1, #1			; Clock hi
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
182 183 184

; Delay here must be >= 4.0 microsecs

Neil Turton's avatar
Neil Turton committed
185 186
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
187

Neil Turton's avatar
Neil Turton committed
188
	Pull	"R1, PC",,^
Neil Turton's avatar
Neil Turton committed
189

Neil Turton's avatar
Neil Turton committed
190 191 192 193 194
ClockData0 ROUT				; Clock a zero bit
	Push	"R0, R14"
	MOV	R0, #0
	BL	ClockData
	Pull	"R0, PC",,^
Neil Turton's avatar
Neil Turton committed
195 196 197

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
198
;	Start - Send the Start signal
Neil Turton's avatar
Neil Turton committed
199
;
Neil Turton's avatar
Neil Turton committed
200
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
201 202
;

Neil Turton's avatar
Neil Turton committed
203 204
Start	ROUT
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
205

Neil Turton's avatar
Neil Turton committed
206 207 208
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
209

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

Neil Turton's avatar
Neil Turton committed
212 213 214
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
215

Kevin Bracey's avatar
Kevin Bracey committed
216
 [ :LNOT: ClockNVMemoryFast
Neil Turton's avatar
Neil Turton committed
217 218
; Hold start condition for BMU

Neil Turton's avatar
Neil Turton committed
219
	MOV	R2, #IOC
Kevin Bracey's avatar
Kevin Bracey committed
220
        MOV     R0, #10
Neil Turton's avatar
Neil Turton committed
221
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
222 223
 ]

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

Neil Turton's avatar
Neil Turton committed
226 227 228
	MOV	R0, #0			; clock LO, data LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
229

Neil Turton's avatar
Neil Turton committed
230
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
231 232 233

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

Acknowledge ROUT
Neil Turton's avatar
Neil Turton committed
242
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
243

Neil Turton's avatar
Neil Turton committed
244 245 246
	MOV	R0, #1			; clock LO, data HI
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
247 248 249 250 251

 [ {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
252 253 254 255
	MOV	R1,PC
	Push	"R1"
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
256
 ]
Neil Turton's avatar
Neil Turton committed
257 258 259
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
260

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

Neil Turton's avatar
Neil Turton committed
263 264
	MOV	R2, #IOC
	LDRB	R2, [R2, #IOCControl]	; get the data from IOC
Neil Turton's avatar
Neil Turton committed
265

Neil Turton's avatar
Neil Turton committed
266 267 268
	MOV	R0, #0
	MOV	R1, #0			; clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
269 270

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
271 272
	Pull	"R1"
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
273 274
 ]

Neil Turton's avatar
Neil Turton committed
275 276 277 278 279
	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
280

Neil Turton's avatar
Neil Turton committed
281
	Pull	"R0-R2,PC"
Neil Turton's avatar
Neil Turton committed
282 283 284

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
285
;	Stop - Send the Stop signal
Neil Turton's avatar
Neil Turton committed
286
;
Neil Turton's avatar
Neil Turton committed
287
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
288 289
;

Neil Turton's avatar
Neil Turton committed
290 291
Stop	ROUT
	Push	"R0,R1,R14"
Neil Turton's avatar
Neil Turton committed
292

Neil Turton's avatar
Neil Turton committed
293 294 295
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
296

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

Neil Turton's avatar
Neil Turton committed
299 300 301
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
302

Neil Turton's avatar
Neil Turton committed
303
	Pull	"R0,R1,PC",,^
Neil Turton's avatar
Neil Turton committed
304 305 306

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
307
;	TXByte - Transmit a byte
Neil Turton's avatar
Neil Turton committed
308
;
Neil Turton's avatar
Neil Turton committed
309
; in:	R0 = byte to be transmitted
Neil Turton's avatar
Neil Turton committed
310
;
Neil Turton's avatar
Neil Turton committed
311
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
312 313
;

Neil Turton's avatar
Neil Turton committed
314 315 316
TXByte	ROUT
	Push	"R0-R2,R14"
	MOV	R1, #&80		; 2^7 the bit mask
Kevin Bracey's avatar
Kevin Bracey committed
317
	MOV	R2, R0			; byte goes into R2
Neil Turton's avatar
Neil Turton committed
318
10
Neil Turton's avatar
Neil Turton committed
319 320 321 322 323 324
	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
325 326 327

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
328 329 330 331 332 333
;	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
334
;
Neil Turton's avatar
Neil Turton committed
335
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
336 337
;

Neil Turton's avatar
Neil Turton committed
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353
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
354

Neil Turton's avatar
Neil Turton committed
355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
; *****************************************************************************
;
;	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
372 373 374 375 376
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
377 378 379 380
	MOV	R1,PC
	Push	"R1"
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
381
 ]
Neil Turton's avatar
Neil Turton committed
382 383 384
	MOV	R0, #1			; pulse clock HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
385

Neil Turton's avatar
Neil Turton committed
386 387 388
	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
389

Neil Turton's avatar
Neil Turton committed
390 391 392
	MOV	R0, #1			; return clock LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
393 394

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
395 396
	Pull	"R1"
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
397
 ]
Neil Turton's avatar
Neil Turton committed
398 399 400 401 402 403 404 405 406 407 408 409 410
	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
411

Neil Turton's avatar
Neil Turton committed
412 413 414 415 416 417 418 419 420 421 422 423
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
424 425 426

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

Kevin Bracey's avatar
Kevin Bracey committed
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
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
451 452 453
	Push	"R0-R4, R14"
	BL	MangleCMOSAddress
	Pull	"R0-R4, PC", CS		; if invalid, then exit
Kevin Bracey's avatar
Kevin Bracey committed
454 455 456 457 458
05
  [ E2ROMSupport
        CMP     r0, #&10
        Pull    "R0-R4, PC", CC         ; don't write to OTP section
  ]
Neil Turton's avatar
Neil Turton committed
459

Neil Turton's avatar
Neil Turton committed
460 461 462 463 464 465 466 467 468
	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
469

Neil Turton's avatar
Neil Turton committed
470 471 472 473
	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
474 475
10
 [ CacheCMOSRAM
Kevin Bracey's avatar
Kevin Bracey committed
476 477 478 479 480 481
	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
482 483
  ]
	STRB	R3, [R1, R2]		; real hardware as well
Kevin Bracey's avatar
Kevin Bracey committed
484
15
Neil Turton's avatar
Neil Turton committed
485 486 487 488 489 490 491
 ]
 [ 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
492 493
 ]

Neil Turton's avatar
Neil Turton committed
494 495
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
496

Kevin Bracey's avatar
Kevin Bracey committed
497 498 499 500 501
        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
502
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
503

Neil Turton's avatar
Neil Turton committed
504 505
	MOV	R0, R3			; data
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
506

Neil Turton's avatar
Neil Turton committed
507 508 509 510 511 512 513 514 515
	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
516

Kevin Bracey's avatar
Kevin Bracey committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 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
; *****************************************************************************
;
;       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
        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

        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
731 732
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
733 734
;	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
735
;       ReadWithError - Read a byte of CMOS RAM specified by logical address, giving error if out of range
Neil Turton's avatar
Neil Turton committed
736
;
Neil Turton's avatar
Neil Turton committed
737
; in:	R0 = address in CMOS RAM
Neil Turton's avatar
Neil Turton committed
738
;
Kevin Bracey's avatar
Kevin Bracey committed
739
; out:	R0 = data (illegal address return 0, or error for ReadWithError)
Neil Turton's avatar
Neil Turton committed
740
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
741 742 743
;

ReadStraight ROUT
Neil Turton's avatar
Neil Turton committed
744 745
	Push	"R1,R2,R14"
	B	%FT10
Neil Turton's avatar
Neil Turton committed
746

Kevin Bracey's avatar
Kevin Bracey committed
747 748 749 750 751 752 753 754 755 756 757 758 759
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
760
Read
Neil Turton's avatar
Neil Turton committed
761 762 763 764
	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
765
10
Neil Turton's avatar
Neil Turton committed
766 767 768
  [	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
769 770 771 772 773
	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
774
  ]
Kevin Bracey's avatar
Kevin Bracey committed
775 776
	LDRCCB	R0, [R2, R0]		; read from cache
	Pull	"R1,R2,PC", CC		; and exit
Neil Turton's avatar
Neil Turton committed
777 778 779
15

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

Neil Turton's avatar
Neil Turton committed
782 783 784 785 786
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]
Neil Turton's avatar
Neil Turton committed
787

Neil Turton's avatar
Neil Turton committed
788 789 790
	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
791

Kevin Bracey's avatar
Kevin Bracey committed
792 793 794 795 796
        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
797
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
798

Neil Turton's avatar
Neil Turton committed
799
	BL	Start
Neil Turton's avatar
Neil Turton committed
800

Neil Turton's avatar
Neil Turton committed
801 802
	ADD	R0, R1, #1		; device address for read
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
803

Neil Turton's avatar
Neil Turton committed
804 805
	BL	RXByte			; returned in R0
	MOV	R2, R0			; copy to R2 for now
Neil Turton's avatar
Neil Turton committed
806

Neil Turton's avatar
Neil Turton committed
807 808
	MOV	R0, #1
	BL	ClockData
Neil Turton's avatar
Neil Turton committed
809

Neil Turton's avatar
Neil Turton committed
810
	BL	Stop
Neil Turton's avatar
Neil Turton committed
811

Neil Turton's avatar
Neil Turton committed
812
	MOV	R0, R2			; return the result
Neil Turton's avatar
Neil Turton committed
813

Neil Turton's avatar
Neil Turton committed
814
	Pull	"R1,R2,PC"
Neil Turton's avatar
Neil Turton committed
815

Kevin Bracey's avatar
Kevin Bracey committed
816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 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

; *****************************************************************************
;
;       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
1122 1123
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1124 1125
;	GetI2CAddress - Convert NVRam physical address to i2c device address
;	                and offset
Neil Turton's avatar
Neil Turton committed
1126
;
Neil Turton's avatar
Neil Turton committed
1127
; in:	R0 = NVRam physical address (&00..size of NVRam)
Neil Turton's avatar
Neil Turton committed
1128
;
Neil Turton's avatar
Neil Turton committed
1129
; out:	R0 preserved
Neil Turton's avatar
Neil Turton committed
1130
;
Neil Turton's avatar
Neil Turton committed
1131 1132 1133
;	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
1134
;	      by 1 for reading. Bit 8 is set if device requires 2-byte physical address.
Neil Turton's avatar
Neil Turton committed
1135
;
Neil Turton's avatar
Neil Turton committed
1136 1137 1138 1139 1140 1141
;	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
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151
	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
1152 1153
	ORRCSS	PC, R14, #C_bit		; indicate invalid

Kevin Bracey's avatar
Kevin Bracey committed
1154 1155 1156
; address is < end address -> is valid
	[ :LNOT: :DEF: TestHarness
	MOV	R1, #0
Neil Turton's avatar
Neil Turton committed
1157
	LDRB	R1, [R1, #RTCFitted]
Kevin Bracey's avatar
Kevin Bracey committed
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
	|
	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
1172

Kevin Bracey's avatar
Kevin Bracey committed
1173 1174 1175 1176 1177
	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
1178
	BICS	PC, R14, #C_bit		; indicate valid
Kevin Bracey's avatar
Kevin Bracey committed
1179

Neil Turton's avatar
Neil Turton committed
1180
  ]
Neil Turton's avatar
Neil Turton committed
1181 1182 1183


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
1184 1185 1186 1187 1188
;
;	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
1189
; in:	R0 = logical address (&00...)
Neil Turton's avatar
Neil Turton committed
1190
;
Kevin Bracey's avatar
Kevin Bracey committed
1191 1192
; out:	C=0 => valid logical address
;	 R0 = physical address (&40..&FF,&10..&3F,&00..0F,&100..)
Neil Turton's avatar
Neil Turton committed
1193
;
Kevin Bracey's avatar
Kevin Bracey committed
1194
;	C=1 => invalid logical address
Neil Turton's avatar
Neil Turton committed
1195 1196
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
1197

Neil Turton's avatar
Neil Turton committed
1198
MangleCMOSAddress ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
 [ 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
1223

Neil Turton's avatar
Neil Turton committed
1224 1225 1226
	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
1227
	BICS	PC, R14, #C_bit		; valid
Neil Turton's avatar
Neil Turton committed
1228 1229 1230

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1231 1232
;	ValChecksum - test to see if the CMOS checksum is OK
;
Kevin Bracey's avatar
Kevin Bracey committed
1233 1234 1235 1236 1237
;       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
1238
;
Neil Turton's avatar
Neil Turton committed
1239
; in:	none
Neil Turton's avatar
Neil Turton committed
1240
;
Neil Turton's avatar
Neil Turton committed
1241 1242 1243
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1244 1245
;

Neil Turton's avatar
Neil Turton committed
1246
  [ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1247

Kevin Bracey's avatar
Kevin Bracey committed
1248
ValChecksum	ENTRY "R1-R2"
Neil Turton's avatar
Neil Turton committed
1249

Kevin Bracey's avatar
Kevin Bracey committed
1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
        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
1260 1261

;
Kevin Bracey's avatar
Kevin Bracey committed
1262
; R1 contains the actual checksum. Compare it with the recorded checksum
Neil Turton's avatar
Neil Turton committed
1263
;
Kevin Bracey's avatar
Kevin Bracey committed
1264 1265 1266
40
	MOV	R0, #CheckSumCMOS
	BL	Read
Neil Turton's avatar
Neil Turton committed
1267
	AND	R2, R0, #&FF		; value from checksum location
Kevin Bracey's avatar
Kevin Bracey committed
1268
	AND	R0, R1, #&FF		; calculated value into R0
Neil Turton's avatar
Neil Turton committed
1269
	CMPS	R0, R2
Neil Turton's avatar
Neil Turton committed
1270

Neil Turton's avatar
Neil Turton committed
1271 1272
	EXIT
  ]
Neil Turton's avatar
Neil Turton committed
1273 1274 1275

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1276
;	MakeChecksum - calculate and write a correct checksum
Neil Turton's avatar
Neil Turton committed
1277
;
Neil Turton's avatar
Neil Turton committed
1278
; in:	none
Neil Turton's avatar
Neil Turton committed
1279
;
Neil Turton's avatar
Neil Turton committed
1280 1281
; out:	R0 = calculated checksum
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
1282 1283
;

Neil Turton's avatar
Neil Turton committed
1284
	[ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
1285

Neil Turton's avatar
Neil Turton committed
1286
MakeChecksum	ROUT
Kevin Bracey's avatar
Kevin Bracey committed
1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297
	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
1298 1299
	MOV	R0, #CheckSumCMOS
	BL	Write
Kevin Bracey's avatar
Kevin Bracey committed
1300
	Pull	"R1-R2,PC"
Neil Turton's avatar
Neil Turton committed
1301
	]
Neil Turton's avatar
Neil Turton committed
1302

Kevin Bracey's avatar
Kevin Bracey committed
1303 1304
        LTORG

Neil Turton's avatar
Neil Turton committed
1305 1306
; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1307
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
1308
;
Neil Turton's avatar
Neil Turton committed
1309 1310 1311 1312 1313 1314 1315 1316 1317
; 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
1318
;
Neil Turton's avatar
Neil Turton committed
1319
;	Any of the above, if -1, will not be written to
Neil Turton's avatar
Neil Turton committed
1320 1321 1322
;

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

Kevin Bracey's avatar
Kevin Bracey committed
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342
	[ :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
1343 1344
; write year to CMOS RAM

Neil Turton's avatar
Neil Turton committed
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379
	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
1380
30
Neil Turton's avatar
Neil Turton committed
1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400
	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
1401

Neil Turton's avatar
Neil Turton committed
1402 1403 1404 1405 1406 1407
40
	MOV	R0, R4			; put hours back in R0
  [ :LNOT: :DEF: TestHarness
	BL	RTCToRealTime
  ]
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1408 1409 1410

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1411
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
1412
;
Neil Turton's avatar
Neil Turton committed
1413
; in:	-
Neil Turton's avatar
Neil Turton committed
1414
;
Neil Turton's avatar
Neil Turton committed
1415 1416 1417 1418 1419 1420 1421 1422
; 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
1423 1424 1425
;

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 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
	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
1477 1478

; Ensure day/month are non-zero, fixes RTCToRealTime
Neil Turton's avatar
Neil Turton committed
1479 1480 1481 1482 1483
 [ {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
1484
 ]
Neil Turton's avatar
Neil Turton committed
1485
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
1486 1487 1488

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
1489 1490 1491 1492
;	InitCMOSCache - Initialise cache of CMOS RAM

  [	CacheCMOSRAM

Kevin Bracey's avatar
Kevin Bracey committed
1493
InitCMOSCache	ENTRY "r0-r5"
Neil Turton's avatar
Neil Turton committed
1494 1495
    [	E2ROMSupport

Kevin Bracey's avatar
Kevin Bracey committed
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
; 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
1509 1510 1511 1512 1513
;	256 byte blocks that we've found

	; Have we got an RTC ?
	MOV	R0, #RTCAddress
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531
	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

; 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
1532 1533

; Have we got a 1K E ?
Kevin Bracey's avatar
Kevin Bracey committed
1534
        MOV     r1, #E2ROMAddress
Neil Turton's avatar
Neil Turton committed
1535 1536
	MOV	r0, #(E2ROMAddress+6)
	BL	DummyAccess
Kevin Bracey's avatar
Kevin Bracey committed
1537
	MOVVC	R4, #4
Neil Turton's avatar
Neil Turton committed
1538 1539 1540 1541 1542
	BVC	%FT5

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

Kevin Bracey's avatar
Kevin Bracey committed
1546 1547 1548
; 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
1549

Kevin Bracey's avatar
Kevin Bracey committed
1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561
        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)
      ]
	MOVVS   R1, #RTCAddress
        MOVVS   R5, #8          ; 256 byte page size for CMOS

5
Neil Turton's avatar
Neil Turton committed
1562
	; Set the NVRam count
Kevin Bracey's avatar
Kevin Bracey committed
1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579
	[ :LNOT: :DEF: TestHarness
	STRB    R1, [R2, #NVRamBase]
	STRB	R4, [R2, #NVRamSize]
        STRB    R5, [R2, #NVRamPageSize]
      [ 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
1580 1581

	; Initialise the cache
Kevin Bracey's avatar
Kevin Bracey committed
1582 1583 1584 1585 1586 1587 1588 1589 1590
        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
1591 1592 1593
    |
	MOV	R1, #RTCAddress
	MOV	R2, #&10
Kevin Bracey's avatar
Kevin Bracey committed
1594 1595 1596 1597 1598 1599
	MOV	R4, #&100		; stop at address &100
        [	:LNOT: :DEF: TestHarness
	LDR	R3, =CMOSRAMCache
        |
	ADR	R3, i2cWorkSpace
        ]
Neil Turton's avatar
Neil Turton committed
1600
    ]
Kevin Bracey's avatar
Kevin Bracey committed
1601
09
Neil Turton's avatar
Neil Turton committed
1602
	BL	Start
Neil Turton's avatar
Neil Turton committed
1603

Neil Turton's avatar
Neil Turton committed
1604 1605
	MOV	R0, R1			; write address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1606

Kevin Bracey's avatar
Kevin Bracey committed
1607 1608 1609 1610 1611
        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
1612
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1613

Neil Turton's avatar
Neil Turton committed
1614
	BL	Start
Neil Turton's avatar
Neil Turton committed
1615

Kevin Bracey's avatar
Kevin Bracey committed
1616
	ORR	R0, R1, #1		; read address
Neil Turton's avatar
Neil Turton committed
1617
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
1618 1619

10
Neil Turton's avatar
Neil Turton committed
1620 1621 1622
	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
1623 1624
	CMP	R2, R4			; stop when we hit end address
	BGE	%FT20
Neil Turton's avatar
Neil Turton committed
1625

Kevin Bracey's avatar
Kevin Bracey committed
1626 1627 1628
	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
1629
	BL	ClockData
Kevin Bracey's avatar
Kevin Bracey committed
1630 1631 1632 1633 1634 1635 1636 1637
	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
1638
20
Neil Turton's avatar
Neil Turton committed
1639 1640 1641
	MOV	R0, #1			; finish off reading block
	BL	ClockData
	BL	Stop
Kevin Bracey's avatar
Kevin Bracey committed
1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676

   [ 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
1677
	EXIT
Kevin Bracey's avatar
Kevin Bracey committed
1678
   ]
Neil Turton's avatar
Neil Turton committed
1679

Neil Turton's avatar
Neil Turton committed
1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
  ]


; *****************************************************************************
;
;	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
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 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 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
; *****************************************************************************
;
;       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
1846
	END