sb-ocr / ocreeb-mk-2

Modular Macro Keyboard System

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

decode module nr in pulse count fast

crbyxwpzfl opened this issue · comments

commented

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.