MCU Line Time Clock and Maintenance Register


Fourth Experiment - Line Time Clock

Normally an operating system requires a regular interrupt to maintain various states, like timers, time-outs or the internal clock. Typically this was created by hardware that interrupted the CPU for every cycle of the mains power, hence you often see 50Hz or 60Hz as the base for the clock interrupt.

Another common option introduced with the DCJ11 based CPU boards was the so called maintenance register. This information contained information about the CPU module version, e.g. 11/53, 11/73 or 11/93, the power-up configuration and additional options like the optional UNIBus adapter available for the 11/84 and 11/94.

Both features can be easily added to the CPLD and do not require MCU interaction except for the clock source that in this case is produced by a timer in the MCU and not the mains frequency.

The line time clock is typically just a single register in the IO-Page at address 1775468 and defines only two valid bits.

Bit 7 reflects the state of the line time clock input and bit 6 enables the line time clock interrupt.

Line Time Clock Register

The line time clock register is implemented in the CPLD. The register has just two bits. Bit7 is the status of the LTC signal and Bit6 is the EVENT interrupt enable bit. Bit 6 is reset by INIT and blocks the event signal. When bit 6 is set the CPLD will activate the EVENT signal.

A new signal INTIO has been defined and has been added to the ABORT logic as valid registers. The CPLD will implement two registers the Line Time Clock Control and Status Register and the KDJ11-E Maintenance Register. Caution the Maintenance Register is a system register.

/*
	Line Time Clock
 */
INTIO         =  LBS1 & !LBS0 &  IOADDR:['o'177546];

APPEND
DAL.oe        =  LBS1 & !LBS0 &  BUFCTL & LAIO:[AIOREAD]  & IOADDR:['o'177546]
              #  LBS1 & !LBS0 &  BUFCTL & LAIO:[AIOINST]  & IOADDR:['o'177546];

APPEND
DAL7          =  IOADDR:['o'177546] & LTC;

APPEND
DAL6          =  LAIO:[AIOREAD] & IOADDR:['o'177546] & LCIE
              #  LAIO:[AIOINST] & IOADDR:['o'177546] & LCIE;

LCIE.ck       =  LBS1 & !LBS0 & LAIO:[AIOWRITE] & IOADDR:['o'177546] & !SCTL;
LCIE.d        =  DAL6.io;
LCIE.ar       =  INIT;

EVENT.ck      =  LTC;
EVENT.d       =  LCIE;
EVENT.ar      =  INIT
              #  LAIO:[AIOGPWRITE] & GPADDR:['o'100] &  STRB;

DCJ11 Event Input

The DCJ11 has a dedicated input for a regular timer interrupt, called EVENT. Typical operating system expect a 60Hz or 50Hz signal, the same frequency as the power line, hence the name line time clock for this device.

EVENT is supposed to be asserted 50 or 60 times per second. The DCJ11 will respond with a special interrupt acknowledge cycle, a GPWRITE to address 1008. This GPWRITE is supposed to deassert EVENT. The DCJ11 will save the current PS and PC onto the stack and fetch the new PS and PC from the vector at address 1008 and start executing the interrupt service routine.

As you can guess the EVENT output of the CPLD is connected to the EVENT input of the DCJ11. And the output is enabled/disabled via bit 6 of the LTC register, named LCIE (line time clock interrupt enable).

50Hz/60Hz Source

There is a dedicated signal between the CPLD and the MCU, called LTC. This signal is expected to carry either the 60Hz or 50Hz clock. On the MCU side this signal is connected to pin PB2. This is also the default for Waveform Output 2 of timer TCA 1.

The MCU operates TCA1 in single slope mode and compare mode 2 enabled. That is the counter continuously counts from 0 to value in the period buffer. Compare register 2 is set to half the value of the period buffer to create a clock signal with 50% duty cycle, although the duty cycle is not important as the hardware only evaluates the leading edge. Then we set PB2 as output and enable the compare mode 2.

The MCU is normally operated at 24Mhz and by using a pre-scaler value of 64 the period buffer must be either set to 6249 or 7499 for a 60Hz or a 50Hz clock signal respectively.

Once configured the timer runs for ever and does not need any further interaction by the MCU.

;
;	TCA1 used as line time clock timer
;
;	We use a prescaler of 64 and period to 6250-1, at 24MHz CPU clock this
;	corresponds to 24'000'000/64/6250 = 60Hz. LTC is pin PB2 which is the
;	default pin for WO2 of TCA1. Therefore we enable CMP2 and set the
;	threshold for the output polarity to half the period which is 3125-1
;	this should result in a 60Hz output with 50% duty cycle.
;
;	For 50Hz the period must be set to 7500-1 and the compare value to 
;	3750-1.
;
.equ	ltcperiod	= F_CPU/64/linefrequency
	sbi	d_LTC			; 

	ldi	r16, low(ltcperiod-1)
	sts	TCA1_SINGLE_PERBUF+0, r16
	ldi	r16, high(ltcperiod-1)
	sts	TCA1_SINGLE_PERBUF+1, r16
	ldi	r16, low(ltcperiod/2-1)
	sts	TCA1_SINGLE_CMP2BUF+0, r16
	ldi	r16, high(ltcperiod/2-1)
	sts	TCA1_SINGLE_CMP2BUF+1, r16
	ldi	r16, TCA_SINGLE_CMP2EN_bm | TCA_SINGLE_WGMODE_SINGLESLOPE_gc
	sts	TCA1_SINGLE_CTRLB, r16
	ldi	r16, TCA_SINGLE_CLKSEL_DIV64_gc | TCA_SINGLE_ENABLE_bm
	sts	TCA1_SINGLE_CTRLA, r16

Maintenance Register

This just returns the status bits as defined in the KDJ11-E manual. It is important to note that the address 1777508 is in the range of the system registers, wich is not part of bank 0b01 and not part of the bank 0b10 of the external registers.

/*
	Maintenance Register

	The maintenance register (17 777 750) is mostly a copy of the power up mode word. 
	Bits 4:7 define the module ID
		Module	ID	Name
		KDJ11-A 0b0001	11/73A
		KDJ11-B 0b0010	11/83 11/84
		KDJ11-D 0b0100	11/53
		KDJ11-E	0b0101	11/93 11/94

	+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
	|B15|B14|B12|B12| 0 | 0 |UNI|FPA|mod|mod|mod|mod|HLT|PU |PU |POK|
	+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
	\______________/      |   |   | \_______________/ | \_______/ |
	        |             |   |   |           |       |     |     |
	        v      	      |   |   |           |       |     |     |
	Boot address   	      |   |   |           |       |     |     |
	reserved <------------+   |   |           |       |     |     |
	UNIBUS <------------------+   |           |       |     |     |
	FPA Present <-----------------+           |       |     |     |
	Module <----------------------------------+       |     |     |
	Halt option (0=ODT, 1=Trap 4)<--------------------+     |     |
	Power Up mode <-----------------------------------------+     |
	Power OK <----------------------------------------------------+

	On a KDJ11-E B15..12 always read as 0b0000.


 */

APPEND
DAL.oe        = !LBS1 &  LBS0 &  BUFCTL & LAIO:[AIOREAD]  & IOADDR:['o'177750]
              # !LBS1 &  LBS0 &  BUFCTL & LAIO:[AIOINST]  & IOADDR:['o'177750];

APPEND        /*   5432109876543210 */
DAL           = 'b'0000000001010011 & LAIO:[AIOREAD] & IOADDR:['o'177750]
              # 'b'0000000001010011 & LAIO:[AIOINST] & IOADDR:['o'177750];

If the module is reported to be a 11/93 then the newest version of the operating systems, like RT-11 V5.7 or RSX-11Mplus 4.2, will use the TOY to set the system time and date.