decode module nr in pulse count fast
crbyxwpzfl opened this issue · comments
hi this is so cool of you @sb-ocr! ok disclaimer im writing this in my brake rn I will revise this later the example likely is faulty currently
tldr.
perhaps this helps to decode the module nr. in the interrupt pulses fast enough.
import board
import array
import adafruit_pioasm
import rp2pio
count prof = adafruit_pioasm.assemble( """
.program counter
mov ~y y ; initial prep for addpulse
reset: ; this block initiates grace time and waits till pin is low
set x 11111 ; set retry counter or grace period max 5bit
wait 0 pin 0 ; wait till pin is low
findedge: ; this tries to find pulse or exits
jmp pin addpulse ; when pin high add one to pulse count
jmp x— exit ; else exit when grace period is zero
jmp findedge ; else retry
addpulse: ; this adds one to pulse counter
jmp y— ; adds one since y is inversed in exit
jmp reset ; reset grace period and test for next pulse
exit: ; this writes pulse count to isr
jmp y! reset ; when y zero alias no pulses detected reset
mov ~y y ; inverses y/pulse count so isr is filled with real count
mov isr y ; depletes y to zero and fills isr
mov ~y y ; inverses y to prep it for addpulse
push noblock ; push isr and do not wait for empty tx fifo
"""
countpio = rp2pio.StateMachine(
program = countprog,
frequency = 0, # 125MHz pio clock speed
jmp_pin = board.A0, # interrupt line pin
)
pulsecount = array.array( 'L', [32] )
while True:
while countpio.in_waiting() < 1: # wait until at least one count is available
pass
while countpio.in_waiting() > 0: # read all words in fifo
countpio.readinto(pulsecount) # read from rx fifo
print(pulsecount[0])
countpio.clear_rxfifo() # reset rx fifo to make room for new counts
limits since one instruction takes 8ns at 125MHz
11111bin/32dec *8ns = 256ns is the grace period until pulse count is reset
2 *8ns = 16ns is the minimum high time for one pulse
i dont know the minimum low time of a pulse but perhaps 8ns duno
assumes a default low state of the interrupt line
tx fifo contains up to 4 pulse counts then counts are lost
dwell time for one pulse count until the next is 7 *8ns = 56ns
more info
this is circuit python. with rp2pio and adafruit_pioasm libraries from adafruit you can init a pio of the rp2040 to count pulses until no pulse is detected for 256ns (but this is adjustable). After one count the pio needs 56ns then it’s ready to count again (perhaps this can be helped by using two pios). So no simultaneous inputs are possible like this. I think. anyways feel free to close this at anytime this is just a thought
or perhaps encode the module nr. in pulse width
this is to read pulse length you need rp2pio and adafruit_pioasm libraries. source of the pio code
import board
import adafruit_pioasm
import rp2pio
pwminprog = adafruit_pioasm.assemble( """
.program PwmIn
; algorithm:
; loop:
; reset the 'timer'
; loop:
; decrement timer
; test for falling edge
; record timer value as pulse width (actually, (0xFFFFFFFF - x)*2/125MHz is the pulse width)
; loop:
; test for rising edge
; decrement timer
; record the timer value as period (actually, (0xFFFFFFFF - x)*2/125MHz is the period)
.wrap_target
mov x ~NULL ; start with the value 0xFFFFFFFF
timer:
jmp x-- test ; count down
jmp timerstop ; timer has reached 0, stop count down
test:
jmp pin timer ; test if the pin is still 1, if so, continue counting down
timerstop: ; pulse is over (or timer has reached 0)
mov ISR x ; move the value in x to the ISR: the pulsewidth (0xFFFFFFFF-pulsewidth)
push noblock ; push the ISR into the RX FIFO
timer2:
jmp pin timerstop2 ; if the pin has become 1, the period is over, stop count down
jmp x-- timer2 ; if not: count down
timerstop2:
mov ISR x ; move the value in x to the ISR: the period (0xFFFFFFFF-period)
push noblock ; push the ISR into the RX FIFO
.wrap
"""
pwminpio = rp2pio.StateMachine(
program = pwminprog,
frequency = 0,
jmp_pin = board.A0,
in_shift_right = False,
)
lowtime = array.array( 'L', [32] )
hightime = array.array( 'L', [32] )
while True:
pwminpio.clear_rxfifo()
while pwminpio.in_waiting() < 2:
pass
pwminpio.readinto(hightime)
print(hightime[0])
pwminpio.readinto(lowtime)
print(hightime[0])
even more info
im not too good at programming and quite new to this in general. anyways
I saw your video and your issue with missing inputs due to pulling inefficiencies. you proposed to encode the module nr. in the interrupt pulses. I recently tried to read a pwm signal of a phillips hue lamp and had the same issue with circuit python being to slow. I solved the issue by reading the signal via a pio of the rp2040. hope this is relevant to you since it is all circuit python it shloud be possible to integrate without a rewrite in c or so
Hey, this is amazing! thank you for taking the time to detail your suggestion.
I will definitely try it when I get to working on that issue.