class SquareOscillator: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, square_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count self._count_freq = count_freq def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still # produces a narrow pulse value = clamp(value, -1, self._max_count) self._sm.put(value) # Converts Hertz to the value the state machine running the PIO # program needs def get_pitch(self, hertz): return int(-1 * (((self._count_freq / hertz) - (self._max_count * 4)) / 4))
class PIOBeep: def __init__(self, sm_id, pin): self.square_sm = StateMachine(0, square_prog, freq=freq, sideset_base=Pin(pin)) #pre-load the isr with the value of max_count self.square_sm.put(max_count) self.square_sm.exec("pull()") self.square_sm.exec("mov(isr, osr)") #note - based on current values of max_count and freq # this will be slightly out because of the initial mov instructions, #but that should only have an effect at very high frequencies def calc_pitch(self, hertz): return int(-1 * (((1000000 / hertz) - 20000) / 4)) def play_value(self, note_len, pause_len, val): self.square_sm.active(1) self.square_sm.put(val) sleep(note_len) self.square_sm.active(0) sleep(pause_len) def play_pitch(self, note_len, pause_len, pitch): self.play_value(note_len, pause_len, self.calc_pitch(pitch))
class WS2812(): def __init__(self, pin, num): # Configure the number of WS2812 LEDs. self.led_nums = num self.pin = pin self.sm = StateMachine(0, ws2812, freq=8000000, sideset_base=self.pin) # Start the StateMachine, it will wait for data on its FIFO. self.sm.active(1) self.buf = array.array("I", [0 for _ in range(self.led_nums)]) def write(self): self.sm.put(self.buf, 8) def write_all(self, value): for i in range(self.led_nums): self.__setitem__(i, value) self.write() def list_to_hex(self, color): if isinstance(color, list) and len(color) == 3: c = (color[0] << 8) + (color[1] << 16) + (color[2]) return c elif isinstance(color, int): value = (color & 0xFF0000) >> 8 | (color & 0x00FF00) << 8 | ( color & 0x0000FF) return value else: raise ValueError( "Color must be 24-bit RGB hex or list of 3 8-bit RGB") def hex_to_list(self, color): if isinstance(color, list) and len(color) == 3: return color elif isinstance(color, int): r = color >> 8 & 0xFF g = color >> 16 & 0xFF b = color >> 0 & 0xFF return [r, g, b] else: raise ValueError( "Color must be 24-bit RGB hex or list of 3 8-bit RGB") def __getitem__(self, i): return self.hex_to_list(self.buf[i]) def __setitem__(self, i, value): value = self.list_to_hex(value) self.buf[i] = value
class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value)
class PIOPWM: def __init__(self, sm_id, pin, count_freq, max_count=(1 << 16) - 1): print(pin) self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count self._pin = pin def _set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse if value>self._max_count: self._sm.active(0) print("off: ", value) Pin(self._pin, Pin.OUT).value(1) else: if not(self._sm.active()): self._sm.put(self._max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) print("on: ", value) value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) print(value) self._sm.put(value)
def button2_handler(pin): @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1).side(0)[T3 - 1] jmp(not_x, "do_zero").side(1)[T1 - 1] jmp("bitloop").side(1)[T2 - 1] label("do_zero") nop().side(0)[T2 - 1] # Create the StateMachine with the ws2812 program, outputting on Pin(22). sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(28)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) for i in up: buzzer.freq(i) buzzer.duty_u16(19660) utime.sleep(0.15) buzzer.duty_u16(0) utime.sleep(0.5) ar = array.array("I", [0 for _ in range(NUM_LEDS)]) ar[0] = 100 sm.put(ar, 8) time.sleep_ms(500) ar[0] = 100 << 8 sm.put(ar, 8) time.sleep_ms(500) ar[0] = 100 << 16 sm.put(ar, 8) time.sleep_ms(500) ar[0] = 0 sm.put(ar, 8)
class DHT11_PIO: def __init__(self, data_pin): pin = Pin(data_pin, Pin.IN, Pin.PULL_UP) self.sm = StateMachine(0) self.sm.init(DHT11, freq=500000, set_base=pin, in_base=pin) self.start = SmAddr(0) def read(self): # Reset the state machine to start a fresh transaction SmRestart(0) SmExec(0, self.start) # Activate the state machine and then sleep until it should be complete self.sm.active(1) utime.sleep_ms(20) self.sm.active(0) # Exception if the amount of data is wrong if SmRxLevel(0) != 2: while SmRxLevel(0): self.sm.get() raise Timeout() # Read back the data from the Rx FIFO as data = self.sm.get() data = (data << 20) + self.sm.get() # Calculate and check checksum if (sum(data >> i * 8 for i in range(1, 5)) - data) & 255: raise BadChecksum() return self.decode(data) def decode(self, data): humidity = (data >> 32 ) & 255 #DHT11 provides integer humidity (no decimal part) temperature = ( data >> 16 ) & 255 #DHT11 provides signed integer temperature (no decimal part) return humidity, temperature
mov(y, osr) # step pattern pull() mov(x, osr) # num steps jmp(not_x, "end") label("loop") jmp(not_osre, "step") # loop pattern if exhausted mov(osr, y) label("step") out(pins, 4)[31] nop()[31] nop()[31] nop()[31] jmp(x_dec, "loop") label("end") set(pins, 8)[31] # 8 sm = StateMachine(0, prog, freq=10000, set_base=Pin(2), out_base=Pin(2)) sm.active(1) sm.put(2216789025) #1000 0100 0010 0001 1000010000100001 sm.put(1000) sleep(5) sm.active(0) sm.exec("set(pins,0)")
class neopixel: ########### Variables ########### numLED = 1 # Number of LEDs in series dataPin = 22 # DIN Pin on RP2040 def RGB(R,G,B): return int(R<<16 | G <<8 | B) # Color definitions BLACK = RGB(0,0,0) WHITE = RGB(255,255,255) RED = RGB(255,0,0) GREEN = RGB(0,255,0) BLUE = RGB(0,0,255) YELLOW = RGB(255,255,0) MAGENTA = RGB(255,0,255) CYAN = RGB(0,255,255) COLORS = [BLACK, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, WHITE] # Placeholders dataArray = None stateMachine = None brightnessOffset = 1 ########### Functions ########### # State Machine Assembly for sending the bitstream to LEDs @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def driver(): T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] # Constructor def __init__(self, LEDS=1, PIN=22): self.numLED = LEDS self.dataPin = PIN # Create the State Machine with the driver program. self.stateMachine = StateMachine(0, self.driver, freq=8000000, sideset_base=Pin(self.dataPin)) # Start the StateMachine self.stateMachine.active(1) # Create data buffer for holding RGB Values self.dataArray = array.array("I", [0 for _ in range(self.numLED)]) # Set single or all LEDs def set(self, LED_NUMBER=None, R=0xFF, G=0xFF, B=0xFF, COLOR=None, brightness=1): self.brightnessOffset = brightness if(LED_NUMBER==None): if(COLOR==None): for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = int(self.brightnessOffset * (R<<8 | G <<16 | B)) else: for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = int(self.brightnessOffset *(((COLOR&0xFF0000)>>8) | ((COLOR&0xFF00)<<8) | ((COLOR&0xFF)))) else: if(COLOR==None): self.dataArray[LED_NUMBER] = int(self.brightnessOffset * (R<<8 | G <<16 | B)) else: self.dataArray[LED_NUMBER] = int(self.brightnessOffset * (((COLOR&0xFF0000)>>8) | ((COLOR&0xFF00)<<8) | ((COLOR&0xFF)))) self.stateMachine.put(self.dataArray,8) # Reset Given or All LED def reset(self, LED_NUMBER=None): if(LED_NUMBER==None): for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = 0 self.stateMachine.put(self.dataArray,8) else: self.dataArray[LED_NUMBER] = 0 self.stateMachine.put(self.dataArray,8) # Change Brightness of Single or All LEDs def setBrightness(self, LED_NUMBER=None, brightness=1): self.brightnessOffset = brightness if(LED_NUMBER==None): for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = int(brightness * self.dataArray[LED_NUMBER]) else: self.dataArray[LED_NUMBER] = int(brightness * self.dataArray[LED_NUMBER]) self.stateMachine.put(self.dataArray,8) # For testing individual LEDs def test(self): for j in range(0,self.numLED): for i in range(0,len(self.COLORS)): self.setLED(LED_NUMBER=j, COLOR=self.COLORS[i]) time.sleep_ms(500) self.resetALL()
def bt3_transition(): @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1).side(0)[T3 - 1] jmp(not_x, "do_zero").side(1)[T1 - 1] jmp("bitloop").side(1)[T2 - 1] label("do_zero") nop().side(0)[T2 - 1] # Create the StateMachine with the ws2812 program, outputting on Pin(28). sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(28)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) # Display a pattern on the LEDs via an array of LED RGB values. ar = array.array("I", [0 for _ in range(NUM_LEDS)]) # RGB demo def rgb_transition(): # grb = 0, 0, inc for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = j sm.put(ar, 8) time.sleep_ms(delay1) # grb = 0, inc, 255 for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = j << 8 | 255 sm.put(ar, 8) time.sleep_ms(delay1) # grb = 0, 255, dec for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = 255 << 8 | (255 - j) sm.put(ar, 8) time.sleep_ms(delay1) # grb = inc, 255, 0 for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = j << 16 | 255 << 8 | 0 sm.put(ar, 8) time.sleep_ms(delay1) # grb = 255, dec, 0 for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = 255 << 16 | (255 - j) << 8 | 0 sm.put(ar, 8) time.sleep_ms(delay1) # grb = 255, 0, inc for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = 255 << 16 | j sm.put(ar, 8) time.sleep_ms(delay1) # grb = 255, inc, 255 for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = 255 << 16 | j << 8 | 255 sm.put(ar, 8) time.sleep_ms(delay1) # grb = dec, dec, dec for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = (255 - j) << 16 | (255 - j) << 8 | (255 - j) sm.put(ar, 8) time.sleep_ms(delay1) rgb_transition()
class DHT(object): def __init__(self, pin: Pin, state_machine_id: int = 0, min_interval: int = 2000): """ Create a DHT object to get communication and get data from DHT sensor. :param pin: Pin connected to DHT's data pin :param state_machine_id: State Machine ID, default value 1 :param min_interval: Minimum interval between communication with DHT, default value 2000 (for DHT22) :type pin: machine.Pin :type state_machine_id: int :type min_interval: int """ self._pin = pin self._last_pull_time = None self._temperature = None self._humidity = None self._min_interval = min_interval # 1 cycle should be 10 us, 1s = 1,000,000us so freq should be 100,000 self._sm = StateMachine(state_machine_id, dht_get_data, freq=100000, set_base=pin) self._sm.irq(handle_dht_irq) self._sm.active(1) def _get_data_from_sensor(self, force: bool = False): if force or self._last_pull_time is None or \ fabs(ticks_diff(ticks_ms(), self._last_pull_time)) > self._min_interval: global _irq_count, temp_data _irq_count = 0 for i in range(5): temp_data[i] = 0 # start state machine self._sm.put(0) # Wait for state machine work utime.sleep_ms(20) if _irq_count != 5: print( "Didn't receive enough data. Received {} byte(s).".format( len(temp_data))) return # data validation, 1st byte + 2nd byte + 3rd byte + 4th byte == 5th byte (last 8 bits) check_sum = (temp_data[0] + temp_data[1] + temp_data[2] + temp_data[3]) & EIGHT_1_BIT_MASK if check_sum != temp_data[4]: print('Data validation error.') return # temperature data is last 15 bits, first bit if 1, is negative. data is 10x of actual value raw_temperature = ( (temp_data[2] & SEVEN_1_BIT_MASK) << 8) + temp_data[3] self._temperature = raw_temperature / 10 if temp_data[2] >> 7 == 1: self._temperature *= -1 raw_humidity = (temp_data[0] << 8) + temp_data[1] # humidity data is 10x of actual value self._humidity = raw_humidity / 10 self._last_pull_time = ticks_ms() def get_temperature(self, force: bool = False) -> float: """ Get temperature from DHT :param force: Force communicate with DHT sensor :type force: bool :return: Last measured temperature :rtype: float """ self._get_data_from_sensor(force) return self._temperature def get_humidity(self, force: bool = False) -> float: """ Get humidity from DHT :param force: Force communicate with DHT sensor :type force: bool :return: Last measured humidity :rtype: float """ self._get_data_from_sensor(force) return self._humidity def get_temperature_and_humidity(self, force: bool = False) -> (float, float): """ Get temperature and humidity from DHT :param force: Force communicate with DHT sensor :type force: bool :return: Last measured temperature and humidity :rtype: (float, float) """ self._get_data_from_sensor(force) return self._temperature, self._humidity
# via the put() command. In each instance of the asm codeexecution, # the asm code will first set the pin low, then decrement Y by 1 in a loop # until y matches x. When y = x = 200, line 14 is called once, setting # the pin high. With the pin set high, y continues to decrement by 1 until 0. # Then the asm is repeated and the pin is set to low again. Therefore, # setting x to 200 will result the pin to be high 200/500 of the times, # corresponding to a 40% duty cycle. # State Machine init pwm_sm = StateMachine(0, pwm_prog, freq=10000000, sideset_base=Pin(16)) # State Machine pwm_sm.put(max_count) # Put data in output FIFO pwm_sm.exec("pull()") pwm_sm.exec("mov(isr, osr)") # Load val into ISR pwm_sm.active(1) # PWM Test #while True: # for i in range(max_count): # pwm_sm.put(i) # sleep(0.001) # for i in range(max_count): # pwm_sm.put(max_count - i) # sleep(0.001) # Jerkky Motion # pwm_sm.put(0) # sleep(1) # pwm_sm.put(max_count) # sleep(2)
def f2b(f): sm = StateMachine(3, nop, freq=f) print(sm.active()) sm.active(0) return mem32[SM3_CLKDIV]
from rp2 import PIO, StateMachine, asm_pio from machine import Pin import time @asm_pio(set_init=PIO.OUT_LOW) def led_off(): set(pins, 0) @asm_pio(set_init=PIO.OUT_LOW) def led_on(): set(pins, 1) sm1 = StateMachine(1, led_off, freq=20000, set_base=Pin(25)) sm2 = StateMachine(2, led_on, freq=20002, set_base=Pin(25)) sm1.active(1) sm2.active(1)
## from machine import Pin import time import rp2 from rp2 import PIO, StateMachine, asm_pio @asm_pio(out_init=rp2.PIO.OUT_LOW) def count_blink(): pull(block) set(pins, 1)[19] nop()[19] nop()[19] nop()[19] nop()[19] set(pins, 0)[19] nop()[19] nop()[19] nop()[19] nop()[19] # create an instance of the state machine sm0 = StateMachine(0, count_blink, freq=2000, out_base=Pin(0)) # start the state machine sm0.active(1) sm0.put(1) time.sleep(2) sm0.active(0)