# =============================================================================
# SAID Test Vector Player - Raspberry Pi Pico (MicroPython) v5
# Kaynak: 26819_SAID_Setup1_PreNoTime_VectorsR2.PCF
#
# v4 → v5 düzeltmesi: CLK glitch sorunu giderildi
#
# Sorun:
# RP2040'ta 16-bit halfword DMA yazmaları 32-bit PIO FIFO'suna
# replicated (kopyalanmış) şekilde yazılır: 0x0555 → 0x05550555
# Bu, bazı silikon versiyonlarında undefined behavior yaratır ve
# FIFO'nun boş kalmasına (underrun) neden olur → PIO stall → CLK glitch
#
# Çözüm: SHIFT_LEFT + val << 20
# Her 12-bit vektör 32-bit word'ün MSB tarafına yerleştirilir.
# out(pins, 12) her seferinde tam 12 bit alır, artık bit kalmaz.
# pull_thresh=12: her out'tan sonra anında yeni word çekilir.
# Mükemmel hizalama → sıfır FIFO underrun → sıfır glitch.
#
# v4 (hatalı): array 'H' (uint16) + DMA HALFWORD + SHIFT_RIGHT
# v5 (doğru): array 'L' (uint32, val<<20) + DMA WORD + SHIFT_LEFT
# =============================================================================
import rp2
import machine
import array
import uctypes
import time
from vectors_data import RLE_VECTORS
# ---------------------------------------------------------------------------
# PIO: 125 MHz, 19 çevrim = 152 ns/vektör
#
# SHIFT_LEFT + pull_thresh=12:
# DMA 32-bit word gönderir, MSB'deki 12 bit pinlere basılır,
# kalan 20 bit (sıfır) shift edilir, hemen yeni word çekilir.
# Her word = tam 1 vektör. Stall yok, glitch yok.
# ---------------------------------------------------------------------------
@rp2.asm_pio(
out_init=(rp2.PIO.OUT_LOW,) * 12,
out_shiftdir=rp2.PIO.SHIFT_LEFT, # ← MSB'den başla (v4'te SHIFT_RIGHT idi)
autopull=True,
pull_thresh=12,
)
def _pio_vector_out():
out(pins, 12) [18] # 19 çevrim × 8 ns = 152 ns
# ---------------------------------------------------------------------------
# RP2040 DMA Register Adresleri
# ---------------------------------------------------------------------------
DMA_CH0_READ = 0x50000000
DMA_CH0_WRITE = 0x50000004
DMA_CH0_COUNT = 0x50000008
DMA_CH0_CTRL = 0x5000000C
PIO0_TXF0 = 0x50200010
DMA_EN = 1 << 0
DMA_DATA_WORD = 2 << 2 # 32-bit WORD (v4'te HALFWORD idi)
DMA_INCR_READ = 1 << 4
DMA_TREQ_PIO0TX = 0 << 15
DMA_BUSY = 1 << 24
# ---------------------------------------------------------------------------
# Adım 1: Vektörleri RAM'e aç — uint32, her değer << 20 ile MSB'ye yerleştir
# ---------------------------------------------------------------------------
print("Vektorler RAM'e aciliyor...")
buf = array.array('L', [0] * 9526) # 'L' = uint32
idx = 0
for val, cnt in RLE_VECTORS:
shifted = val << 20 # 12-bit değeri MSB'ye taşı
for _ in range(cnt):
buf[idx] = shifted
idx += 1
print(f" {idx} vektor hazir ({idx*4//1024} KB)")
# ---------------------------------------------------------------------------
# Adım 2: PIO + LED
# ---------------------------------------------------------------------------
led = machine.Pin(25, machine.Pin.OUT)
sm = rp2.StateMachine(
0, _pio_vector_out,
freq=125_000_000,
out_base=machine.Pin(0),
)
# ---------------------------------------------------------------------------
# Adım 3: DMA transferi
# ---------------------------------------------------------------------------
def run(repeat=1):
sm.active(1)
led.on()
src = uctypes.addressof(buf)
ctrl = DMA_EN | DMA_DATA_WORD | DMA_INCR_READ | DMA_TREQ_PIO0TX
for cycle in range(repeat):
machine.mem32[DMA_CH0_READ] = src
machine.mem32[DMA_CH0_WRITE] = PIO0_TXF0
machine.mem32[DMA_CH0_COUNT] = len(buf)
machine.mem32[DMA_CH0_CTRL] = ctrl
while machine.mem32[DMA_CH0_CTRL] & DMA_BUSY:
pass
print(f"Dongu {cycle+1}/{repeat} tamamlandi")
time.sleep_ms(5)
sm.active(0)
led.off()
print("Test bitti.")
run(repeat=1)