+/*
+ * delay for <count> ms...
+ */
+static void test_delay(uint32_t count)
+{
+ uint32_t ts = get_timer(0);
+
+ while (get_timer(ts) <= count);
+}
+
+static int32_t z80_measure_phi(uint8_t cycles, bool input_clk, uint16_t wait_ms)
+{
+ uint16_t ref_stop;
+ uint16_t ref_ovfl;
+ uint32_t x_freq;
+
+
+ PRR1 &= ~_BV(PRTIM3);
+ TCCR3A = 0;
+ TCCR3B = 0b000<<CS30; /* stop counter */
+ TCNT3 = 0;
+ TIFR3 = _BV(TOV3);
+ ref_ovfl = 0;
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ /* Reset pending int */
+ EIFR = _BV(INTF6);
+ /* Wait for falling edge */
+ while ((EIFR & _BV(INTF6)) == 0)
+ ;
+ //ref_start = TCNT4;
+ OCR4B = TCNT4;
+ TCCR3B = 0b110<<CS30; /* Count falling edges on T3 (==INT6) */
+ TIFR4 = _BV(OCF4B); /* clear compare match flag */
+ }
+ while (ref_ovfl < 60) {
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ if ((TIFR4 & _BV(OCF4B)) != 0) {
+ TIFR4 = _BV(OCF4B);
+ ref_ovfl++;
+ }
+ }
+ }
+
+ ATOMIC_BLOCK(ATOMIC_FORCEON) {
+ EIFR = _BV(INTF6);
+ for (;;) {
+ if (EIFR & _BV(INTF6))
+ break;
+ if (TIFR4 & _BV(OCF4B)) {
+ if (EIFR & _BV(INTF6))
+ break;
+ TIFR4 = _BV(OCF4B);
+ if (EIFR & _BV(INTF6))
+ break;
+ ref_ovfl++;
+ if (EIFR & _BV(INTF6))
+ break;
+ if (ref_ovfl == 0)
+ break;
+ }
+ }
+ ref_stop = TCNT4;
+ TCCR3B = 0b000<<CS30; /* stop counter */
+ if ((TIFR4 & _BV(OCF4B)) != 0) {
+ TIFR4 = _BV(OCF4B);
+ if (ref_ovfl)
+ ref_ovfl++;
+ }
+ }
+
+ if (ref_ovfl == 0)
+ x_freq = 0xFFFFFFFE;
+ else
+ {
+ uint32_t ref_cnt = (ref_stop - OCR4B) + ((uint32_t)ref_ovfl << 16);
+
+ x_freq = TCNT3; /* x_cnt (17 bit) */
+ if ((TIFR3 & _BV(TOV3)) != 0)
+ x_freq += 1UL << 16;
+ uint32_t x_cnt = x_freq;
+ if (input_clk) /* compute input clock */
+ x_freq *= 2;
+ x_freq *= cycles;
+
+ x_freq = ((uint64_t) x_freq * F_CPU + (ref_cnt / 2))/ ref_cnt;
+
+ printf_P(PSTR("ref_start: %6u, ref_stop: %6u, ref_ovfl: %4u, ref_cnt: %9lu\n"
+ " TCNT3: %6u, x_cnt: %6lu, cycles: %3u, xfreq: %9lu\n"),
+ OCR4B, ref_stop, ref_ovfl, ref_cnt,
+ TCNT3, x_cnt, cycles, x_freq);
+
+ /* round to 5 decimal digits */
+ uint8_t sc = 0;
+ while (x_freq >= 100000UL) {
+ x_freq = (x_freq + 5)/10;
+ ++sc;
+ }
+ while (sc--)
+ x_freq *= 10;
+ }
+
+ /* Stop Timer */
+ TCCR3B = 0;
+ PRR1 |= _BV(PRTIM3);
+
+ return (int32_t) x_freq;
+}
+
+