What a “bug”!!!

01.02.2020

I had a rather unpleasant 15 hours (2 days nearly straight) bug hunting behind me, that really wore me out.

See that „High score“?
That is the second vector cluster in „Tailgunner“ (when starting). You see that shaking? That was driving me nuts! I did not want the shaking!
The first 1-2 hours I tried figuring out what it its, and when it occured. As it turned out…

  • it only appears to be in the first or second „vector cluster“ (lists after a zero).
  • the shaking only happens when some sort of drift correction was active.
  • The shaking is random. Sometimes about 5-6 times a second, sometimes not at all.

Last night (after about 10 hours hunting) I was ready to throw the whole stuff away and not do any PiTrex anymore. Really – I had it… I rewrote all vector routines. I tried different pipeline sorting. I programmed modes without pipeline refresh… etc etc etc.

The behaviors was not explainable and not predictable.

After a bad nights sleep (and breakfast, doing some shopping and cleaning up…). I set down again. (Terrier!)

Than I thought, that somehow the memory management of my list was awry – that I’d overwrite some items. But after digging deeper that also rendered no results.

After stripping down the pipeline to the bare essentials I had a version where there were no disturbances… After more experiments it turned out that was pure coincident, removing a simple „printf“ statement resulted in the flickering to return.

Anyway after again a few hours I began to concentrate on a function: „v_resetIntegratorOffsets“, which as the name suggests ensures clean integrator offsets AND if drift calibration is active – ensures the correct drift calibration, which is exactly the integrator offset.
(For more explanation see: http://vide.malban.de/25th-of-janurary-2018-vpatrol-ingenuity-part-i)

inline static void v_resetIntegratorOffsets()
{
  SET (VIA_port_b, 0x81);
  DELAY_PORT_B_BEFORE_PORT_A();
  SET (VIA_port_a, 0x00);
  DELAY_CYCLES(4);
  SET (VIA_port_b, 0x80);
  DELAY_CYCLES(4);
  if (calibrationValue==0)
  {
    // reset integrators
    SET (VIA_port_b, 0x82);   
    DELAY_CYCLES(6);
    SET (VIA_port_b, 0x81);   
  }
  else
  {
    SET (VIA_port_b, 0x81);
    DELAY_PORT_B_BEFORE_PORT_A();
    SET (VIA_port_a, calibrationValue);
    DELAY_CYCLES(4);
    SET (VIA_port_b, 0x82);
    DELAY_CYCLES(4);
    SET (VIA_port_a, 0xff);
    DELAY_CYCLES(2);       <-----------!!!!!
    SET (VIA_port_b, 0x81);
  }
  DELAY_CYCLES(4);
}

Ok, long words – short story. The gist of my problem (which I found out a few minutes ago) is the about marked line.

As you have read above (link) – the drift correction Tuts style – is in fact the exact „breaking“ of a capacitor discharging. Keyword here being EAXCT.As it turns out the time between …

-> start timer
    SET (VIA_port_a, 0xff);
    DELAY_CYCLES(2);
    SET (VIA_port_b, 0x81);
-> end timer

… is very often 4000 nanoseconds (+-50) – which in vectrex cylces is 6 cycles.

But once and again the timing is about 4700 (+ something) which in vectrex cycles is 7 cycles.

(@Graham: Thx again for that cycle count tip!!!)

The flickering you see in the gif – is exactly that one cycle difference. About 666 nanoseconds discharging of a capacitor inside the vectrex, with the function of „offset to the integrators“.
WHY the flickering only occurs in the first or second vector cluster – is absolutely beyond me. Also why the pitrex delays sometimes more, sometimes less (you see the above function – all values, settings pitrex „pokings” are always EXACTLY the same – why is there a difference that far in the function?) Why have all the other „aligned“ SET function not settled to a fixed „pitrex“ timing slot? I don’t know.

What I know is, I must ENSURE that  the setting of:   

    SET (VIA_port_a, 0xff);
...
    SET (VIA_port_b, 0x81);

Is (as exactly as possibly) 4 vectrex cycles apart. If there is only one cycle difference a flickering hell breaks lose.
As it turns out – this is not so difficult (although I still have to implement it correctly)…
The DELAY_CYCLES above results in:

// delay in vectrex cycles
void v_delayCycles(uint32_t n)
{
  uint32_t nWait;
  nWait = (n*DELAY_PI_CYCLE_EQUIVALENT)-(OFFSET_CYCLE_OVERHEAD);
  if (nWait>((uint32_t)-20)) return; // if „negative"
  WAIT_CYCLE_NANO(nWait);
}

You might discern – with this function I try to wait „exactly“ the number of nano seconds a vectrex cycle lasts.
But since the GET/SET functions of the pitrex actually have to wait internally for the next RDY signal to arrive on the vectrex bus… If I wait for e.g. 4 cycles with the delay…and we are a little bit to far in the vectrex cycle – the SET function actually itself waits another (nearly) complete cycle to process the request…
So the best strategy (if I use the delay function in combination with pitrex IO) is to wait for say… 1.1 cycles instead of 2.

That way I ensure I wait in the delay „more“ than 1 – the „rest“ of the second cycle is waited for in the „SET“ function anyway.

This bloody stupid shaking bug, might actually result in an overall speedup of all my output…
Geee….

02.02.2020

After the above I did some “easy” stuff for the show…

Black Widow (except sound of course) is completely playable with two joysticks!

Space Duel dito – also with two players with two joysticks!

And a proof video…