Ok, I just returned to this project. Can you tell me I didn't get anything wrong and I do understand the MC6840 work correctly?
The initialization code looks as follows:
Code:
void __fastcall__ mc6840_init (void) {
MC6840_CON13 = TM_COUNTER_OUTPUT_ENABLE | TM_INTERUPT_DISABLE | TM_CONT_OP_MODE1 | TM_NORMAL_16BIT | TM_SYS_CLK | TMCR3_T3_CLK_NO_PRESCALER; //CON3 first by default after reset. TIMER3 generates sound. Output enable and sys clk
MC6840_CON2 = TM_COUNTER_OUTPUT_ENABLE | TM_INTERUPT_ENABLE | TM_CONT_OP_MODE1 | TM_NORMAL_16BIT | TM_SYS_CLK | TMCR2_WRITE_CR1; //CON2 accessed directly..TIMER2 is used for systick and time base for DCF77. Output enabled and sys clk.
MC6840_CON13 = TM_COUNTER_OUTPUT_DISABLE | TM_INTERUPT_ENABLE | TM_PULSE_WIDTH_COMP_MODE1 | TM_NORMAL_16BIT | TM_EXT_CLK | TMCR1_ALL_TIMERS_ALLOWED; //CON1. TIMER1 to measure DCF77 pulses length, so external source and interrupt enabled.
//Remember about endianess - MC6800 family is big endian, 6502 is little endian. Remember that timer is decremented.
MC6840_TIMER1 = Swap2Bytes(0xFFFF);
MC6840_TIMER2 = Swap2Bytes(0x9E57); //25ms interrupt (0xFFFF - 25000) - it is decremented!
MC6840_TIMER3 = Swap2Bytes(0xF82F); //500 Hz signal on audio output
}
There is an interrupt routine for TIMER1 (set in pulse width mode):
Code:
LDA MC6840_STA ; Load TIMER status register
AND #$01 ; Check if TIMER1 IRQ flag is set
BEQ irq_chk_rtc ; If flag is cleared, go to the next stage
LDA MC6840_TIMER1 ; You must read T1 to clear interrupt flag
TAX ; This is MSB, transfer it to X
LDA MC6840_TIMER1+1 ; This is LSB, it stays in A
JSR _dcf_analyze ; DCF77 being processed here
LDA #$FF ; Reload timer
STA MC6840_TIMER1 ; MSB Fir
STA MC6840_TIMER1 + 1 ; Then LSB
This is a dcf_analyze function:
Code:
void __fastcall__ dcf_analyze (uint16_t len) {
uint8_t tmp, tmp2;
uint16_t pulse_len;
pulse_len = 0xFFFF - len; //Timer counts in reverse, so we need to convert
tmp=dcf_count/8;
tmp2=dcf_count%8;
if (pulse_len < 3) { //Pulse shorter than 75ms (3*25ms) - invalid
dcf_count = 0; //Clear bit count
}
else if (pulse_len >= 3 && pulse_len <= 5) { //Valid bit 0 75-125 ms (100 ms)
dcf_data[tmp] = dcf_data[tmp] & (~(1<<tmp2)); //writnig 0
dcf_count++; //next bit
}
else if (pulse_len >= 7 && pulse_len <= 9) { //Valid bit 1 175-225 ms (200 ms)
dcf_data[tmp] = dcf_data[tmp] | (1<<tmp2); //writnig 1
dcf_count++; //next bit
}
else if (pulse_len > 39 && pulse_len < 84) { //Valid synchro null 59bit (975-2100 ms)
dcf_count = 0;
}
if (dcf_count > 58) { //End of receiving, now validate data
dcf_count = 0; //Prevent buffer overflow
memcpy(dcf_work_buffer, dcf_data, 8); //Copy received data to work buffer, it will be processed in main loop
dcf_frame_received = 1;
}
}
Tell mi if I understand it correctly:
1. At the beginning, timer should be preloaded with 0xFFFF.
2. It stays still until GATE1 signal goes down.
3. It is decrementing initial timer value (0xFFFF) by 1 with every clock cycle on C1 input (which in my case is 25ms).
4. When GATE1 goes up, it starts counting and interrupt is executed.
5. I need to read the value stored in TIMER1 register, remembering to swap the bytes, because 6502 is little endian.
6. To get the actual number of "ticks" counted while GATE1 was low, I need to subtract this value from 0xFFFF.
7.
Then I need to load TIMER1 with 0xFFFF once again, because otherwise it would start the next count from its last value. It doesn't reload itself automatically, Am I right?
Is there some mistake in my thinking?