|
| 1 | +#https://forums.raspberrypi.com/viewtopic.php?p=1985859#p1984172 |
| 2 | +#Changing frequency of SM while running |
| 3 | + |
| 4 | +#https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf |
| 5 | +# see chapter 4.9.6. List of Registers |
| 6 | +#Clock divisor register for state machine N |
| 7 | +#Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) |
| 8 | + |
| 9 | +#31:16 INT - Effective frequency is sysclk/(int + frac/256). Value of 0 is interpreted as 65536. If INT is 0, FRAC must also be 0 |
| 10 | +#15:8 FRAC - Fractional part of clock divisor |
| 11 | +#7:0 Reserved |
| 12 | + |
| 13 | +import rp2 |
| 14 | +from machine import freq, mem32, Pin |
| 15 | +from time import sleep |
| 16 | + |
| 17 | +def sm_div_calc(target_f): |
| 18 | + if target_f < 0: |
| 19 | + div = 256 |
| 20 | + elif target_f == 0: |
| 21 | + # Special case: set clkdiv to 0. |
| 22 | + div = 0 |
| 23 | + else: |
| 24 | + div = freq() * 256 // target_f |
| 25 | + if div <= 256 or div >= 16777216: |
| 26 | + raise ValueError("freq out of range") |
| 27 | + return div << 8 |
| 28 | + |
| 29 | +@rp2.asm_pio(set_init=rp2.PIO.OUT_LOW) |
| 30 | + |
| 31 | +def signal(): |
| 32 | + wrap_target() |
| 33 | + nop() |
| 34 | + wrap() |
| 35 | + |
| 36 | +def sm_div_ref(target_f): |
| 37 | + sm0 = rp2.StateMachine(0, signal, freq=target_f, set_base=Pin(26)) |
| 38 | + SM0_CLKDIV = 0x50200000 + 0x0c8 |
| 39 | + # convert to signed int value to unsigned int value |
| 40 | + if (mem32[SM0_CLKDIV]<0): |
| 41 | + return mem32[SM0_CLKDIV] + 2**32 |
| 42 | + else: |
| 43 | + return mem32[SM0_CLKDIV] |
| 44 | + |
| 45 | +print("freq():", freq()) |
| 46 | + |
| 47 | +# check if same results for example 2000 are calculated |
| 48 | +tf = 2000 |
| 49 | + |
| 50 | +#x = 0b10000000_00000000_00000010_00000000 |
| 51 | +x = sm_div_ref(tf) |
| 52 | +im = 0b11111111_11111111_00000000_00000000 |
| 53 | +fm = 0b00000000_00000000_11111111_00000000 |
| 54 | + |
| 55 | +i = (x&im)>>16 |
| 56 | +f = (x&fm)>>8 |
| 57 | +cf = freq() / (i + f / 256) |
| 58 | + |
| 59 | +print("sm()", type(x), x, bin(x), i, f , cf, tf) |
| 60 | + |
| 61 | +#using horuable's function to calc clock divider |
| 62 | + |
| 63 | +div = sm_div_calc(tf) |
| 64 | + |
| 65 | +i = (div&im)>>16 |
| 66 | +f = (div&fm)>>8 |
| 67 | +print("python",type(div), div, bin(div), i, f , cf, tf) |
| 68 | + |
| 69 | + |
| 70 | + |
| 71 | +assert sm_div_ref(2000) ^ sm_div_calc(2000) == 0, "register values are different for freq 2000" |
| 72 | + |
| 73 | +for f in [2000, 23413, 213123213, 123123,1000, 12323]: |
| 74 | + try: |
| 75 | + assert sm_div_ref(f) ^ sm_div_calc(f) == 0, "register values are different for freq "+str(f) |
| 76 | + except ValueError as e: |
| 77 | + print(e, "at frequency", str(f)) |
| 78 | + |
| 79 | + |
| 80 | + |
0 commit comments