@@ -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/// ```
16911691static 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