Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 04:36 17 Sep 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : hardware timer that can fire an interrupt ?

     Page 2 of 2    
Author Message
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 12:55pm 15 Sep 2025
Copy link to clipboard 
Print this post

ah,ok. will try. i downloaded the version off Geoffs webpage. I'll go hunting for 6.01
I'll keep yo posted.

I got the MMBASIC interrupt going so MMBasic can decide when to fire the PIO.
Essentially MMbasic listens for the falling edge of the interrupt pin. the ISR is very short. The PIO's react to the rising edge


ISR:

- Set a dac
- if sendmarker=1 then
  load T1 and T2 in Pio1    
  start pio1
  load t3 in pio2
  start pio2
- increment sweepcount


the main program (idle loop)
checks "sweepcount" and makes it roll over when it hits 5.
it also sets and clears the "Sendmarker" flag.


I've had this run overnight (without the actual PIO working. i was firing them but the I/O didn't work)  at 1 millisecond. It didn't miss a single one. So timing-wise we're good. it will do the 4millisecond with time to spare.
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 12:28am 16 Sep 2025
Copy link to clipboard 
Print this post

Now we are getting somewhere.

Is there a way to stop the pio machine from inside the PIO?
i've tricked it by using

.lab HALT
 jmp HALT
[/code]

it works, but is it the right way ? Or is it needed at all? Since there are no further instructions it should stop.
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 01:25am 16 Sep 2025
Copy link to clipboard 
Print this post

hmmm. There is a lot of jitter in the interrupt handler ( not the pio) and executing the I/O code is also jittery.

just doing

pin(gp0)=1
PIO start 1,0

creates jitter between the setting of the pin and launching the PIO. The delay is in the order of 25 to 30 microseconds...

Our "interrupt pulse is about 100 microseconds. MMBasic is too slow to complete what i need to complete in that timeframe

i can live with a fixed delay but the jitter is killing.
There's too many other things going on. (which are understandeable. this things services usb and a bunch of other things. But in my application none if it is necessary. It runs headless.

The pin interrupts are almost the lowest priority in MMbasic. There's too many other things running.

i need to look into cascading PIO. PIO can fire interrupts as well...
If i cascade PIO i can take some of the time critical stuff out of the software interrupt. (amongst which is the decision logic on which sweep to fire the PIO . this is the source of much of the delay and jitter)

THe bigger problem is the following:

I need to ponder a bit on how to do this. this is the problem when you have an "operating system" ( which is essentially what MMBASIC is ) in the way. There's too much household tasks in the background.

Rough sketch:
One pio listens to the hardware interrupt and endlessly counts from 0 to 5.
if the count value equals a loaded number ( the selected sweep number ) it fires a second PIO that is the marker generator. this is done using a hardware output looped back. The same hardware pin triggers a software interrupt that performs calculations and updates the DAC  . But i use an external register. the DAC only truly "updates' on the sweep start bacuse the register latches at that point. It is being precalculated during the previous sweep but only updates at the sweep start. So the time consuming stuff is pushed into the"previous" 4mS and the tie critical stuff canhappen in the retract. The PIO regulate the flow. Essentially the PIO drive the software. not the other way around :)
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5254
Posted: 06:46am 16 Sep 2025
Copy link to clipboard 
Print this post

Hi vincent

PIO can also set the DAC. Just feed it the required DAC value through fifo.
PIO cannot compare values. But if the value is known, it can loop that many syncs before executing.

Using PIO to trigger MMBasic is what I also do in the frequency counter. MMBasic generates a gate pulse that is "inaccurate", and PIO generates from that a clock accurate synchronized gate pulse. And end of that synced gate pulse a GPIO pin informs MMBasic the measured frequency is available.
I know that GPIO pin can be replaced by a PIO interrupt, but during development I found it easier to have a test point where I can see what PIO is doing, and I kept it that way (attached a "gate" LED).

Volhout
PicomiteVGA PETSCII ROBOTS
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 01:41pm 16 Sep 2025
Copy link to clipboard 
Print this post

The pio can only access 5 bits at a time. that is not enough. The dac is a parallel 8 bit device on i/o pins. It's a multiplying current mode dac. can't change that.
But that's not a problem. i will put a 74574 inbetween and have the pio fire the clock pin of it.

i need to flip the logic around. The main program needs to run during the "idle time".
the idle time is the time in the sweeps where we don't need a marker.

That gives the basic side a lot of time to calculate things and set things up.

When the marker Pio has fired (end of the marker sweep) i will send an interrupt to the basic code. That signals "we have just finished, the marker". The Samplers are loaded: do your thing. The program now has 4 sweep cycles. (only one out of 5 cycles has the marker) to process everything and set up new data:

- new T1 and T2 for the markers and new T3 for the sampler

The cycling PIO that counts from 0 to 5 will fire an interrupt after it latched the data to the DAC. That gives the basic interrupt handler for that "tick" a full 4 milliconds to calculate the next DAC value and load it on the pico's i/o is it is ready on the next sweep.

The machine looks like this:


on sweep interrupt (falling edge)
  sweep = sweep +1
  if sweep = 5 then sweep =0
  set the dac with a new value
  if sweep = selectedsweep then start marker_pio <- this one fires on rising edge
end interrupt


But this has tremendous jitter. It can't even arm the marker pio before the rising edge comes.


So i need to flip this around.

The decision to fire stays in the loop and i move everything else outside.

on sweep interrupt(falling edge)
  if sweep = selectedsweep then start marker_pio <- this one fires on rising edge
  ' i do the above first to race the 100uS. the rest now has 5 full sweeps to process
  sweep = sweep+1
  if sweep=5 then sweep = 0


since the 74574 is edge triggered i can wire it to the falling edge ( sweep retract). the DAC will then be ready when the sweep starts.
Since the outer loop now has all the time in the world it can T1 T2 and T3 in the FIFOs and recaculate the next DAC. It doesn't matter if this happens now or in the next pass. The user won't notice. There are 50 cycles of 5 sweeps per second. It doesn't matter if you click the rotary that it didn't happen in the current pass. 20 milliseconds is not perceivable by the human eye.

The pinch point right now is doing multiple things during that short 100uS retract time.

I will have the marker pio trigger the sampler pio. i don't have to start both on the basic side. One pio will launch the other.
Edited 2025-09-16 23:44 by vincenthimpe
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5254
Posted: 01:44pm 16 Sep 2025
Copy link to clipboard 
Print this post

PIO can parallel write 32 bits at a time from FIFO.

Volhout
PicomiteVGA PETSCII ROBOTS
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 02:31pm 16 Sep 2025
Copy link to clipboard 
Print this post

This is the marker program:

it drives 3 outputs :
io3 : start pulse
io2 : Marker polarity
io1 : marker on/off

and listens to
i/o0 : trigger on rising edge


' Marker program
PIO assemble 1,".program marker"

.line 0
  Set pindirs, &b000
  Set pins, &b000

.label lab0
  ' -------- startup --------
  Wait 0,pin,0    
  Set pins, &b000
  Pull noblock        ' get the fifo contents
  Mov x,osr
  Out y,16            ' get t1
  Wait 1,pin,0        ' wait for rising edge
  Set pins, &b100 [2] ' generate a pulse on io3 to signal we have started
  set pins, &b000

  ' ------- first marker ----
.label lab1
  Jmp Y--,lab1
  Set pins,&b001 [21]  ' marker on
  Set pins,&b011 [21]  ' marker polarity change
  Set pins,&b000       ' marker off

  ' ------ second marker ----
  Out y,16            ' get t2
.label lab2
  Jmp y--,lab2
  Set pins,&b001 [21]
  Set pins,&b011 [21]
  Set pins,&b000 [30]
  ' Create a "double" marker here. This gives a double "blip" on the screen
  set pins,&b001 [21]
  set pins,&b011 [21]
  set pins,&b000  

.label lab3   ' go in deadlock.
  Jmp lab3
.end program


The second pio is the "sampler pio"

it drives 1 outputs :
io5 : sample gate

and listens to
i/o4 : trigger on rising edge. this is a wire between IO3 and Io4 so PIO1 can fire PIO2


' Sampler program
PIO assemble 2,".program sampler"

.line 0
  Set pindirs, &b0
  Set pins, &b0

.label lab0
  ' -------- startup --------
  Wait 0,pin,4    
  Set pins, &b1
  Pull noblock        ' get the fifo contents
  Mov x,osr
  Out y,16            ' get t1
  Wait 1,pin,4        ' wait for rising edge
  Set pins, &b1       ' open the gate

  ' ------- first marker ----
.label lab1
  Jmp Y--,lab1
  Set pins,&b0         ' close the gate

.label lab2   ' go in deadlock.
  Jmp lab2
.end program

Edited 2025-09-17 00:31 by vincenthimpe
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 02:32pm 16 Sep 2025
Copy link to clipboard 
Print this post

  Volhout said  PIO can parallel write 32 bits at a time from FIFO.

Volhout

I thought the PIO only has access to 5 sequential IO pins ?
 
Volhout
Guru

Joined: 05/03/2018
Location: Netherlands
Posts: 5254
Posted: 02:41pm 16 Sep 2025
Copy link to clipboard 
Print this post

Look in the RP2040 or RP2350 chip manual for the PIO command OUT (and IN). You can shift out data to n pins from FIFO (n=1...32). The SET command cam maximum set 5 adjacent pins. OUT can do max 32, but they must be adjacent.

Volhout
Edited 2025-09-17 00:42 by Volhout
PicomiteVGA PETSCII ROBOTS
 
vincenthimpe
Regular Member

Joined: 14/10/2018
Location: United States
Posts: 86
Posted: 02:48pm 16 Sep 2025
Copy link to clipboard 
Print this post

  Volhout said  Look in the RP2040 or RP2350 chip manual for the PIO command OUT (and IN). You can shift out data to n pins from FIFO (n=1...32). The SET command cam maximum set 5 adjacent pins. OUT can do max 32, but they must be adjacent.

Volhout

thanks! found the out command.

Adjacent is not a problem.

We need better documentation ... It's all scattered and outdated. a lot of the examples still use handcrafted hex :)
 
Mixtel90

Guru

Joined: 05/10/2019
Location: United Kingdom
Posts: 8079
Posted: 03:14pm 16 Sep 2025
Copy link to clipboard 
Print this post

The PIO actually needs binary to build its commands from the fundamental pieces. Sometimes it's easier to understand &b10000000 than &h80 when you are looking at them. :)  You probably can't compose a list of all the possible PIO commands, it might be bigger than the Datasheet!
Mick

Zilog Inside! nascom.info for Nascom & Gemini
Preliminary MMBasic docs & my PCB designs
 
     Page 2 of 2    
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025