Skip to content

Commit e7e72c9

Browse files
authored
Merge pull request #114 from Neotron-Compute/fix-pixel-timings
Fix pixel timings
2 parents 4efc06a + 41cee80 commit e7e72c9

File tree

1 file changed

+27
-11
lines changed

1 file changed

+27
-11
lines changed

src/vga/mod.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ impl ScanlineTimingBuffer {
685685
// Back porch. Adjusted by a few clocks to account for interrupt +
686686
// PIO SM start latency.
687687
Self::make_timing(
688-
(timings.2 * Self::CLOCKS_PER_PIXEL) - 5,
688+
(timings.2 * Self::CLOCKS_PER_PIXEL) - 10,
689689
hsync.disabled(),
690690
vsync.disabled(),
691691
RaiseIrq::None,
@@ -694,7 +694,7 @@ impl ScanlineTimingBuffer {
694694
// moving. Adjusted to compensate for changes made to previous
695695
// period to ensure scan-line remains at correct length.
696696
Self::make_timing(
697-
(timings.3 * Self::CLOCKS_PER_PIXEL) + 5,
697+
(timings.3 * Self::CLOCKS_PER_PIXEL) + 10,
698698
hsync.disabled(),
699699
vsync.disabled(),
700700
RaiseIrq::Irq0,
@@ -803,7 +803,7 @@ impl ScanlineTimingBuffer {
803803
if vsync {
804804
value |= 1 << 1;
805805
}
806-
value |= (period - 6) << 2;
806+
value |= (period - FIXED_CLOCKS_PER_TIMING_PULSE) << 2;
807807
value | command << 16
808808
}
809809
}
@@ -1690,6 +1690,9 @@ static PIXEL_DATA_BUFFER_ODD: LineBuffer = LineBuffer::new_odd();
16901690
/// ```
16911691
static TEXT_COLOUR_LOOKUP: TextColourLookup = TextColourLookup::blank();
16921692

1693+
/// How many fixed clock cycles there are per timing pulse.
1694+
const FIXED_CLOCKS_PER_TIMING_PULSE: u32 = 5;
1695+
16931696
// -----------------------------------------------------------------------------
16941697
// Functions
16951698
// -----------------------------------------------------------------------------
@@ -1710,28 +1713,41 @@ pub fn init(
17101713
let (mut pio, sm0, sm1, _sm2, _sm3) = pio.split(resets);
17111714

17121715
// This program runs the timing loop. We post timing data (i.e. the length
1713-
// of each period, along with what the H-Sync and V-Sync pins should do)
1714-
// and it sets the GPIO pins and busy-waits the appropriate amount of
1715-
// time. It also takes an extra 'instruction' which we can use to trigger
1716-
// the appropriate interrupts.
1716+
// of each period, along with what the H-Sync and V-Sync pins should do) and
1717+
// it sets the GPIO pins and busy-waits the appropriate amount of time. It
1718+
// also takes an extra 'instruction' which we can use to trigger the
1719+
// appropriate interrupts.
1720+
//
1721+
// Note that the timing period value should be:
1722+
//
1723+
// timing_period = actual_timing_period - FIXED_CLOCKS_PER_TIMING_PULSE
1724+
//
1725+
// This is because there are unavoidable clock cycles within the algorithm.
1726+
// Currently FIXED_CLOCKS_PER_TIMING_PULSE should be set to 5.
17171727
//
17181728
// Post <value:32> where value: <clock_cycles:14> <hsync:1> <vsync:1>
17191729
// <instruction:16>
17201730
//
17211731
// The SM will execute the instruction (typically either a NOP or an IRQ),
1722-
// set the H-Sync and V-Sync pins as desired, then wait the given number
1723-
// of clock cycles.
1732+
// set the H-Sync and V-Sync pins as desired, then wait the given number of
1733+
// clock cycles.
17241734
//
17251735
// Note: autopull should be set to 32-bits, OSR is set to shift right.
17261736
let timing_program = pio_proc::pio_asm!(
17271737
".wrap_target"
1728-
// Step 1. Push next 2 bits of OSR into `pins`, to set H-Sync and V-Sync
1738+
// Step 1. Push next 2 bits of OSR into `pins`, to set H-Sync and V-Sync.
1739+
// Takes 1 clock cycle.
17291740
"out pins, 2"
17301741
// Step 2. Push last 14 bits of OSR into X for the timing loop.
1742+
// Takes 1 clock cycle.
17311743
"out x, 14"
1732-
// Step 3. Execute bottom 16-bits of OSR as an instruction. This take two cycles.
1744+
// Step 3. Execute bottom 16-bits of OSR as an instruction.
1745+
// This take two cycles, always.
17331746
"out exec, 16"
17341747
// Spin until X is zero
1748+
// Takes X + 1 clock cycles because the branch is conditioned on the initial value of the register.
1749+
// i.e. X = 0 => 1 clock cycle (the jmp when x = 0)
1750+
// i.e. X = 1 => 2 clock cycles (the jmp when x = 1 and again when x = 0)
17351751
"loop0:"
17361752
"jmp x-- loop0"
17371753
".wrap"

0 commit comments

Comments
 (0)