i2cutils 19.6 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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
; ***********************************
; ***    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

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

PollMax		*	&f	; Number of times to poll for an Ack

; Device addresses
RTCAddress	* &a0
  [	E2ROMSupport
E2ROMAddress	* &a8
  ]

; i2cWorkSpace is defined elsewhere to point somewhere sensible when debugging
  [ :LNOT: :DEF: TestHarness
i2cWorkSpace	* 0
  ]

Neil Turton's avatar
Neil Turton committed
50 51 52

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

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

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

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

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

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

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

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

Neil Turton's avatar
Neil Turton committed
111 112
	MOV	R0, #10			; delay for >= 10/2 microsecs
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
113

Neil Turton's avatar
Neil Turton committed
114
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
115 116 117

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
118
;	DoMicroDelay - Delay for >= R0/2 microseconds
Neil Turton's avatar
Neil Turton committed
119
;
Neil Turton's avatar
Neil Turton committed
120 121 122
; 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
123
;
Neil Turton's avatar
Neil Turton committed
124
; out:	R0,R1 corrupted
Neil Turton's avatar
Neil Turton committed
125 126 127
;

DoMicroDelay ROUT
Neil Turton's avatar
Neil Turton committed
128
	Push	R14
Neil Turton's avatar
Neil Turton committed
129

Neil Turton's avatar
Neil Turton committed
130 131
	STRB	R0, [R2, #Timer0LR]	; copy counter into output latch
	LDRB	R1, [R2, #Timer0CL]	; R1 := low output latch
Neil Turton's avatar
Neil Turton committed
132
10
Neil Turton's avatar
Neil Turton committed
133 134 135 136 137 138 139
	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
140

Neil Turton's avatar
Neil Turton committed
141
	Pull	PC
Neil Turton's avatar
Neil Turton committed
142

Neil Turton's avatar
Neil Turton committed
143
	LTORG
Neil Turton's avatar
Neil Turton committed
144 145 146

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
147
;	ClockData - Clock a bit of data down the IIC bus
Neil Turton's avatar
Neil Turton committed
148
;
Neil Turton's avatar
Neil Turton committed
149
; in:	R0 = data bit
Neil Turton's avatar
Neil Turton committed
150
;
Neil Turton's avatar
Neil Turton committed
151
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
152 153 154
;

ClockData ROUT
Neil Turton's avatar
Neil Turton committed
155
	Push	"R1, R14"
Neil Turton's avatar
Neil Turton committed
156

Neil Turton's avatar
Neil Turton committed
157 158
	MOV	R1, #0			; Clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
159 160 161 162 163

 [ {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
164 165 166
	MOV	R1,PC
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
167
 ]
Neil Turton's avatar
Neil Turton committed
168 169
	MOV	R1, #1			; Clock hi
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
170 171 172

; Delay here must be >= 4.0 microsecs

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

Neil Turton's avatar
Neil Turton committed
176
	Pull	"R1, PC",,^
Neil Turton's avatar
Neil Turton committed
177

Neil Turton's avatar
Neil Turton committed
178 179 180 181 182
ClockData0 ROUT				; Clock a zero bit
	Push	"R0, R14"
	MOV	R0, #0
	BL	ClockData
	Pull	"R0, PC",,^
Neil Turton's avatar
Neil Turton committed
183 184 185

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
186
;	Start - Send the Start signal
Neil Turton's avatar
Neil Turton committed
187
;
Neil Turton's avatar
Neil Turton committed
188
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
189 190
;

Neil Turton's avatar
Neil Turton committed
191 192
Start	ROUT
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
193

Neil Turton's avatar
Neil Turton committed
194 195 196
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
197 198 199

; Delay here must be >= 4.0 microsecs

Neil Turton's avatar
Neil Turton committed
200 201 202
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
203 204 205 206

 [ {TRUE}
; Hold start condition for BMU

Neil Turton's avatar
Neil Turton committed
207 208 209
	MOV	R2, #IOC
	MOV	R0,#10
	BL	DoMicroDelay
Neil Turton's avatar
Neil Turton committed
210 211 212 213
 ]

; Delay here must be >= 4.7 microsecs

Neil Turton's avatar
Neil Turton committed
214 215 216
	MOV	R0, #0			; clock LO, data LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
217

Neil Turton's avatar
Neil Turton committed
218
	Pull	"R0-R2,PC",,^
Neil Turton's avatar
Neil Turton committed
219 220 221

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
222
;	Acknowledge - Check acknowledge after transmitting a byte
Neil Turton's avatar
Neil Turton committed
223
;
Neil Turton's avatar
Neil Turton committed
224 225 226
; out:	All registers preserved
;	V=0 => acknowledge received
;	V=1 => no acknowledge received
Neil Turton's avatar
Neil Turton committed
227 228 229
;

Acknowledge ROUT
Neil Turton's avatar
Neil Turton committed
230
	Push	"R0-R2,R14"
Neil Turton's avatar
Neil Turton committed
231

Neil Turton's avatar
Neil Turton committed
232 233 234
	MOV	R0, #1			; clock LO, data HI
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
235 236 237 238 239

 [ {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
240 241 242 243
	MOV	R1,PC
	Push	"R1"
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
244
 ]
Neil Turton's avatar
Neil Turton committed
245 246 247
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
248 249 250

; Delay here must be >= 4.0 microsecs

Neil Turton's avatar
Neil Turton committed
251 252
	MOV	R2, #IOC
	LDRB	R2, [R2, #IOCControl]	; get the data from IOC
Neil Turton's avatar
Neil Turton committed
253

Neil Turton's avatar
Neil Turton committed
254 255 256
	MOV	R0, #0
	MOV	R1, #0			; clock lo
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
257 258

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
259 260
	Pull	"R1"
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
261 262
 ]

Neil Turton's avatar
Neil Turton committed
263 264 265 266 267
	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
268

Neil Turton's avatar
Neil Turton committed
269
	Pull	"R0-R2,PC"
Neil Turton's avatar
Neil Turton committed
270 271 272

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
273
;	Stop - Send the Stop signal
Neil Turton's avatar
Neil Turton committed
274
;
Neil Turton's avatar
Neil Turton committed
275
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
276 277
;

Neil Turton's avatar
Neil Turton committed
278 279
Stop	ROUT
	Push	"R0,R1,R14"
Neil Turton's avatar
Neil Turton committed
280

Neil Turton's avatar
Neil Turton committed
281 282 283
	MOV	R0, #0			; clock HI, data LO
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
284 285 286

; Delay here must be >= 4.0 microsecs

Neil Turton's avatar
Neil Turton committed
287 288 289
	MOV	R0, #1			; clock HI, data HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
290

Neil Turton's avatar
Neil Turton committed
291
	Pull	"R0,R1,PC",,^
Neil Turton's avatar
Neil Turton committed
292 293 294

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
295
;	TXByte - Transmit a byte
Neil Turton's avatar
Neil Turton committed
296
;
Neil Turton's avatar
Neil Turton committed
297
; in:	R0 = byte to be transmitted
Neil Turton's avatar
Neil Turton committed
298
;
Neil Turton's avatar
Neil Turton committed
299
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
300 301
;

Neil Turton's avatar
Neil Turton committed
302 303 304 305
TXByte	ROUT
	Push	"R0-R2,R14"
	MOV	R2, R0			; byte goes into R2
	MOV	R1, #&80		; 2^7 the bit mask
Neil Turton's avatar
Neil Turton committed
306
10
Neil Turton's avatar
Neil Turton committed
307 308 309 310 311 312
	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
313 314 315

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
316 317 318 319 320 321
;	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
322
;
Neil Turton's avatar
Neil Turton committed
323
; out:	All registers preserved, including PSR
Neil Turton's avatar
Neil Turton committed
324 325
;

Neil Turton's avatar
Neil Turton committed
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
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
342

Neil Turton's avatar
Neil Turton committed
343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
; *****************************************************************************
;
;	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
360 361 362 363 364
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
365 366 367 368
	MOV	R1,PC
	Push	"R1"
	ORR	R1,R1,#I_bit
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
369
 ]
Neil Turton's avatar
Neil Turton committed
370 371 372
	MOV	R0, #1			; pulse clock HI
	MOV	R1, #1
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
373

Neil Turton's avatar
Neil Turton committed
374 375 376
	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
377

Neil Turton's avatar
Neil Turton committed
378 379 380
	MOV	R0, #1			; return clock LO
	MOV	R1, #0
	BL	SetC1C0
Neil Turton's avatar
Neil Turton committed
381 382

 [ {TRUE}
Neil Turton's avatar
Neil Turton committed
383 384
	Pull	"R1"
	TEQP	PC,R1
Neil Turton's avatar
Neil Turton committed
385
 ]
Neil Turton's avatar
Neil Turton committed
386 387 388 389 390 391 392 393 394 395 396 397 398
	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
399

Neil Turton's avatar
Neil Turton committed
400 401 402 403 404 405 406 407 408 409 410 411
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
412 413 414

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
415
;	Write - Write a byte of CMOS RAM specified by logical address
Neil Turton's avatar
Neil Turton committed
416
;
Neil Turton's avatar
Neil Turton committed
417 418
; in:	R0 = address in CMOS RAM
;	R1 = data
Neil Turton's avatar
Neil Turton committed
419
;
Neil Turton's avatar
Neil Turton committed
420
; out:	All registers preserved
Neil Turton's avatar
Neil Turton committed
421 422
;

Neil Turton's avatar
Neil Turton committed
423 424 425 426
Write	ROUT
	Push	"R0-R4, R14"
	BL	MangleCMOSAddress
	Pull	"R0-R4, PC", CS		; if invalid, then exit
Neil Turton's avatar
Neil Turton committed
427

Neil Turton's avatar
Neil Turton committed
428 429 430 431 432 433 434 435 436
	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
437

Neil Turton's avatar
Neil Turton committed
438 439 440 441
	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
442 443
10
 [ CacheCMOSRAM
Neil Turton's avatar
Neil Turton committed
444 445 446 447 448 449 450 451 452 453 454 455
	ADR	R1, CMOSRAMCache-16	; update cache, but always write to
  [ :DEF: TestHarness
	ADD	R1, R1, #i2cWorkSpace
  ]
	STRB	R3, [R1, R2]		; real hardware as well
 ]
 [ 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
456 457
 ]

Neil Turton's avatar
Neil Turton committed
458 459
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
460

Neil Turton's avatar
Neil Turton committed
461 462
	MOV	R0, R2			; offset
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
463

Neil Turton's avatar
Neil Turton committed
464 465
	MOV	R0, R3			; data
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
466

Neil Turton's avatar
Neil Turton committed
467 468 469 470 471 472 473 474 475
	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
476 477 478

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
479 480
;	Read - Read a byte of CMOS RAM specified by logical address
;	ReadStraight - Read a byte of CMOS RAM specified by physical address
Neil Turton's avatar
Neil Turton committed
481
;
Neil Turton's avatar
Neil Turton committed
482
; in:	R0 = address in CMOS RAM
Neil Turton's avatar
Neil Turton committed
483
;
Neil Turton's avatar
Neil Turton committed
484 485
; out:	R0 = data (illegal address return 0)
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
486 487 488
;

ReadStraight ROUT
Neil Turton's avatar
Neil Turton committed
489 490
	Push	"R1,R2,R14"
	B	%FT10
Neil Turton's avatar
Neil Turton committed
491 492

Read
Neil Turton's avatar
Neil Turton committed
493 494 495 496
	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
497
10
Neil Turton's avatar
Neil Turton committed
498 499 500 501 502 503 504 505
  [	CacheCMOSRAM
	TEQ	R0, #&40		; is it Econet station number
	BEQ	%FT15	 		; if so then don't use cache
	CMP	R0, #&10		; don't cache values < &10
	ADRCS	R2, CMOSRAMCache-&10	; if in range

  [ :DEF: TestHarness
	ADD	R2, R2, #i2cWorkSpace
Neil Turton's avatar
Neil Turton committed
506
  ]
Neil Turton's avatar
Neil Turton committed
507 508
	LDRCSB	R0, [R2, R0]		; read from cache
	Pull	"R1,R2,PC", CS		; and exit
Neil Turton's avatar
Neil Turton committed
509 510 511
15

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

Neil Turton's avatar
Neil Turton committed
514 515 516 517 518
  [	E2ROMSupport
	BL	GetI2CAddress		; convert to device address and offset
  |
	MOV	R1, #RTCAddress
  ]
Neil Turton's avatar
Neil Turton committed
519

Neil Turton's avatar
Neil Turton committed
520 521 522
	MOV	R2, R0			; save the offset
	MOV	R0, R1			; device address for write
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
523

Neil Turton's avatar
Neil Turton committed
524 525
	MOV	R0, R2			; offset
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
526

Neil Turton's avatar
Neil Turton committed
527
	BL	Start
Neil Turton's avatar
Neil Turton committed
528

Neil Turton's avatar
Neil Turton committed
529 530
	ADD	R0, R1, #1		; device address for read
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
531

Neil Turton's avatar
Neil Turton committed
532 533
	BL	RXByte			; returned in R0
	MOV	R2, R0			; copy to R2 for now
Neil Turton's avatar
Neil Turton committed
534

Neil Turton's avatar
Neil Turton committed
535 536
	MOV	R0, #1
	BL	ClockData
Neil Turton's avatar
Neil Turton committed
537

Neil Turton's avatar
Neil Turton committed
538
	BL	Stop
Neil Turton's avatar
Neil Turton committed
539

Neil Turton's avatar
Neil Turton committed
540
	MOV	R0, R2			; return the result
Neil Turton's avatar
Neil Turton committed
541

Neil Turton's avatar
Neil Turton committed
542
	Pull	"R1,R2,PC"
Neil Turton's avatar
Neil Turton committed
543 544 545

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
546 547
;	GetI2CAddress - Convert NVRam physical address to i2c device address
;	                and offset
Neil Turton's avatar
Neil Turton committed
548
;
Neil Turton's avatar
Neil Turton committed
549
; in:	R0 = NVRam physical address (&00..size of NVRam)
Neil Turton's avatar
Neil Turton committed
550
;
Neil Turton's avatar
Neil Turton committed
551
; out:	R0 preserved
Neil Turton's avatar
Neil Turton committed
552
;
Neil Turton's avatar
Neil Turton committed
553 554 555 556
;	C=0 => NVRam address is valid
;	 R0 = physical address within i2c device
;	 R1 = i2c device address for writing. Increment this device address
;	      by 1 for reading.
Neil Turton's avatar
Neil Turton committed
557
;
Neil Turton's avatar
Neil Turton committed
558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
;	C=1 => NVRam address is out of range of CMOS or E2ROM chips
;	 R0 preserved
;	 R1 preserved

  [	E2ROMSupport
GetI2CAddress ROUT
	CMP	R0, #&100
	ORRCSS	PC, R14, #C_bit		; indicate invalid

; address is <&100 -> is valid
	MOV	R1, #i2cWorkSpace
	LDRB	R1, [R1, #RTCFitted]
	TEQ	R1, #1
	MOVEQ	R1, #RTCAddress
	MOVNE	R1, #E2ROMAddress

	BICS	PC, R14, #C_bit		; indicate valid
  ]
Neil Turton's avatar
Neil Turton committed
576 577 578


; *****************************************************************************
Neil Turton's avatar
Neil Turton committed
579 580 581 582 583 584 585 586 587 588 589 590 591
;
;	MangleCMOSAddress - Convert from logical to physical address
;
;	Doesn't check if address is larger than the amount of NVRam installed
;
; in:	R0 = logical address (&00..&EF, &100..)
;
; out:	C=0 => valid logical address (ie not &F0..&FF)
;	 R0 = physical address (&40..&FF,&10..&3F,&100..)
;
;	C=1 => invalid logical address (ie &F0..&FF)
;	 R0 preserved
;
Neil Turton's avatar
Neil Turton committed
592

Neil Turton's avatar
Neil Turton committed
593 594 595
MangleCMOSAddress ROUT
	CMP	R0, #&F0		; if address &f0 or above
	ORRCSS	PC, R14, #C_bit		; indicate invalid
Neil Turton's avatar
Neil Turton committed
596

Neil Turton's avatar
Neil Turton committed
597 598 599 600
	ADD	R0, R0, #&40		; now in range &40..&13F
	CMP	R0, #&100
	SUBCS	R0, R0, #(&100-&10)	; now in range &40..&FF, &10..&3F
	BICS	PC, R14, #C_bit		; indicate valid
Neil Turton's avatar
Neil Turton committed
601 602 603 604


; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
605 606
;	ValChecksum - test to see if the CMOS checksum is OK
;
Neil Turton's avatar
Neil Turton committed
607 608 609
;       This routine performs MangleCMOSAddress inherently, and
;       assumes the checksum is the last logical location.
;
Neil Turton's avatar
Neil Turton committed
610
; in:	none
Neil Turton's avatar
Neil Turton committed
611
;
Neil Turton's avatar
Neil Turton committed
612 613 614
; out:	R0 = calculated checksum
;	Z	set if checksum is valid
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
615 616
;

Neil Turton's avatar
Neil Turton committed
617
  [ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
618

Neil Turton's avatar
Neil Turton committed
619
ValChecksum	ENTRY "R1,R2,R3"
Neil Turton's avatar
Neil Turton committed
620

Neil Turton's avatar
Neil Turton committed
621 622 623 624 625 626 627 628 629
	MOV	R3, #CMOSxseed
    [ E2ROMSupport
	MOV	R0, #&40
	BL	GetI2CAddress		; r1 = device address, r0 = offset
	MOV	R2, R0			; save the offset
    |
	MOV	R2, #&40
	MOV	R1, #RTCAddress
    ]
Neil Turton's avatar
Neil Turton committed
630
10
Neil Turton's avatar
Neil Turton committed
631 632
	MOV	R0, R1	 		; device write address
	BL	StartTXPollAck
Neil Turton's avatar
Neil Turton committed
633

Neil Turton's avatar
Neil Turton committed
634 635
	MOV	R0, R2			; memory offset
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
636

Neil Turton's avatar
Neil Turton committed
637
	BL	Start
Neil Turton's avatar
Neil Turton committed
638

Neil Turton's avatar
Neil Turton committed
639 640
	ADD	R0, R1, #1		; device read address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
641 642

;
Neil Turton's avatar
Neil Turton committed
643
; Read data from locations &40 through &FF, then
Neil Turton's avatar
Neil Turton committed
644 645 646 647
; loop back to &10 (we have to write the address again) and read
; on until &3E .. thus missing out the checksum location.
;
20
Neil Turton's avatar
Neil Turton committed
648 649 650 651 652 653 654 655 656 657 658 659 660
	BL	RXByte			; returned in R0
	ADD	R3, R3, R0		; accumulate into R3

	ADD	R2, R2, #1		; increment R2 to phys. address
	TEQ	R2, #&100		; limit
	BEQ	%30
	TEQ	R2, #PhysChecksum	; or until checksum.
	BEQ	%30			; then we're finished

	MOV	R0, #0			; not done .. ACK that byte
	BL	ClockData
	B	%BT20			; .. and continue reading

Neil Turton's avatar
Neil Turton committed
661
30
Neil Turton's avatar
Neil Turton committed
662 663 664 665 666 667 668
	MOV	R0, #1			; finish off reading block
	BL	ClockData
	BL	Stop

        TST     R2, #&100		; either go back for bytes 10 - 3f
        MOVNE   R2, #&10		; or finish up completely.
	BNE	%BT10
Neil Turton's avatar
Neil Turton committed
669 670 671 672

;
; R3 contains the actual checksum. Compare it with the recorded checksum
;
Neil Turton's avatar
Neil Turton committed
673 674 675 676 677
	MOV	R0, #PhysChecksum
	BL	ReadStraight
	AND	R2, R0, #&FF		; value from checksum location
	AND	R0, R3, #&FF		; calculated value into R0
	CMPS	R0, R2
Neil Turton's avatar
Neil Turton committed
678

Neil Turton's avatar
Neil Turton committed
679 680
	EXIT
  ]
Neil Turton's avatar
Neil Turton committed
681 682 683

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
684
;	MakeChecksum - calculate and write a correct checksum
Neil Turton's avatar
Neil Turton committed
685
;
Neil Turton's avatar
Neil Turton committed
686
; in:	none
Neil Turton's avatar
Neil Turton committed
687
;
Neil Turton's avatar
Neil Turton committed
688 689
; out:	R0 = calculated checksum
;	All other registers preserved
Neil Turton's avatar
Neil Turton committed
690 691
;

Neil Turton's avatar
Neil Turton committed
692
	[ ChecksumCMOS
Neil Turton's avatar
Neil Turton committed
693

Neil Turton's avatar
Neil Turton committed
694 695 696 697 698 699 700 701
MakeChecksum	ROUT
	Push	R14
	BL	ValChecksum
	MOV	R1, R0
	MOV	R0, #CheckSumCMOS
	BL	Write
	Pull	PC
	]
Neil Turton's avatar
Neil Turton committed
702 703 704

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
705
;	SetTime - Write the CMOS clock time and update 5-byte RealTime
Neil Turton's avatar
Neil Turton committed
706
;
Neil Turton's avatar
Neil Turton committed
707 708 709 710 711 712 713 714 715
; 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
716
;
Neil Turton's avatar
Neil Turton committed
717
;	Any of the above, if -1, will not be written to
Neil Turton's avatar
Neil Turton committed
718 719 720
;

SetTime ROUT
Neil Turton's avatar
Neil Turton committed
721
	Push	"R4, R14"		; save registers
Neil Turton's avatar
Neil Turton committed
722 723 724

; write year to CMOS RAM

Neil Turton's avatar
Neil Turton committed
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 750 751 752 753 754 755 756 757 758 759
	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
760
30
Neil Turton's avatar
Neil Turton committed
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
	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
781

Neil Turton's avatar
Neil Turton committed
782 783 784 785 786 787
40
	MOV	R0, R4			; put hours back in R0
  [ :LNOT: :DEF: TestHarness
	BL	RTCToRealTime
  ]
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
788 789 790

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
791
;	ReadTime - Read the CMOS clock time
Neil Turton's avatar
Neil Turton committed
792
;
Neil Turton's avatar
Neil Turton committed
793
; in:	-
Neil Turton's avatar
Neil Turton committed
794
;
Neil Turton's avatar
Neil Turton committed
795 796 797 798 799 800 801 802
; 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
803 804 805
;

ReadTime ROUT
Neil Turton's avatar
Neil Turton committed
806 807 808 809 810 811 812 813 814 815 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
	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
857 858

; Ensure day/month are non-zero, fixes RTCToRealTime
Neil Turton's avatar
Neil Turton committed
859 860 861 862 863
 [ {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
864
 ]
Neil Turton's avatar
Neil Turton committed
865
	Pull	"R4, PC"
Neil Turton's avatar
Neil Turton committed
866 867 868

; *****************************************************************************
;
Neil Turton's avatar
Neil Turton committed
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
;	InitCMOSCache - Initialise cache of CMOS RAM

  [	CacheCMOSRAM

InitCMOSCache	ENTRY "r0-r3"
    [	E2ROMSupport

;	First determine what hardware we've got fitted, R3 holds the number of
;	256 byte blocks that we've found

	; Have we got an RTC ?
	MOV	R0, #RTCAddress
	BL	DummyAccess
	MOVVS	R3, #0
	MOVVC	R3, #1
	MOV	R2, #i2cWorkSpace
	STRB	R3, [R2, #RTCFitted]

; Have we got a 1K E ?
	MOV	r0, #(E2ROMAddress+6)
	BL	DummyAccess
	ADDVC	R3, R3, #4
	BVC	%FT5

; Have we got 512 bytes of E ?
	MOV	r0, #(E2ROMAddress+2)
	BL	DummyAccess
	ADDVC	R3, R3, #4
	BVC	%FT5

; Have we got any E ?
	MOV	r0, #(E2ROMAddress)
	BL	DummyAccess
	ADDVC	R3, R3, #1

	; Set the NVRam count
5	STRB	R3, [R2, #NVRamSize]

	; Initialise the cache
	MOV	R0, #&10
	BL	GetI2CAddress		; convert to device address and offset
	MOV	R2, R0			; save the offset
    |
	MOV	R1, #RTCAddress
	MOV	R2, #&10
    ]
	ADR	R3, CMOSRAMCache-16
Neil Turton's avatar
Neil Turton committed
916

Neil Turton's avatar
Neil Turton committed
917 918 919 920
    [	:DEF: TestHarness
	ADD	R3, R3, #i2cWorkSpace
    ]
	BL	Start
Neil Turton's avatar
Neil Turton committed
921

Neil Turton's avatar
Neil Turton committed
922 923
	MOV	R0, R1			; write address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
924

Neil Turton's avatar
Neil Turton committed
925 926
	MOV	R0, R2			; memory word address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
927

Neil Turton's avatar
Neil Turton committed
928
	BL	Start
Neil Turton's avatar
Neil Turton committed
929

Neil Turton's avatar
Neil Turton committed
930 931
	ADD	R0, R1, #1		; read address
	BL	TXAck
Neil Turton's avatar
Neil Turton committed
932 933

10
Neil Turton's avatar
Neil Turton committed
934 935 936 937 938 939 940 941 942
	BL	RXByte			; returned in R0
	STRB	R0, [R3, R2]
	ADD	R2, R2, #1		; increment R2 to phys. address
	CMP	R2, #&100
	BEQ	%FT20

	MOV	R0, #0			; not done .. ACK that byte
	BL	ClockData
	B	%BT10			; .. and continue reading
Neil Turton's avatar
Neil Turton committed
943
20
Neil Turton's avatar
Neil Turton committed
944 945 946 947
	MOV	R0, #1			; finish off reading block
	BL	ClockData
	BL	Stop
	EXIT
Neil Turton's avatar
Neil Turton committed
948

Neil Turton's avatar
Neil Turton committed
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
  ]


; *****************************************************************************
;
;	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
  ]

	END