|
| 1 | +# SPDX-FileCopyrightText: 2022 Jeff Epler, written for Adafruit Industries |
| 2 | +# |
| 3 | +# SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +"""Demonstrate background writing, including loop writing, with morse code. |
| 6 | +
|
| 7 | +On any rp2040 board with board.LED, this will alternately send 'SOS' and 'TEST' |
| 8 | +via the LED, demonstrating that Python code continues to run while the morse |
| 9 | +code data is transmitted. Alternately, change one line below to make it send |
| 10 | +'TEST' forever in a loop, again while Python code continues to run. |
| 11 | +
|
| 12 | +The combination of "LED status" and duration is sent to the PIO as 16-bit number: |
| 13 | +The top bit is 1 if the LED is turned on and 0 otherwise. The other 15 bits form a delay |
| 14 | +value from 1 to 32767. A subset of the morse code 'alphabit' is created, with everthing |
| 15 | +based on the 'DIT duration' of about 128ms (1MHz / 32 / 4000). |
| 16 | +
|
| 17 | +https://en.wikipedia.org/wiki/Morse_code |
| 18 | +""" |
| 19 | + |
| 20 | +import time |
| 21 | +import array |
| 22 | +from board import LED |
| 23 | +from rp2pio import StateMachine |
| 24 | +from adafruit_pioasm import Program |
| 25 | + |
| 26 | +# This program turns the LED on or off depending on the first bit of the value, |
| 27 | +# then delays a length of time given by the next 15 bits of the value. |
| 28 | +# By correctly choosing the durations, a message in morse code can be sent. |
| 29 | +pio_code = Program( |
| 30 | + """ |
| 31 | + out x, 1 |
| 32 | + mov pins, x |
| 33 | + out x, 15 |
| 34 | + busy_wait: |
| 35 | + jmp x--, busy_wait [31] |
| 36 | + """ |
| 37 | +) |
| 38 | + |
| 39 | + |
| 40 | +# The top bit of the command is the LED value, on or off |
| 41 | +LED_ON = 0x8000 |
| 42 | +LED_OFF = 0x0000 |
| 43 | + |
| 44 | +# The other 15 bits are a delay duration. |
| 45 | +# It must be the case that 4 * DIT_DURATION < 32768 |
| 46 | +DIT_DURATION = 4000 |
| 47 | +DAH_DURATION = 3 * DIT_DURATION |
| 48 | + |
| 49 | +# Build up some elements of morse code, based on the wikipedia article. |
| 50 | +DIT = array.array("H", [LED_ON | DIT_DURATION, LED_OFF | DIT_DURATION]) |
| 51 | +DAH = array.array("H", [LED_ON | DAH_DURATION, LED_OFF | DIT_DURATION]) |
| 52 | +# That is, two more DAH-length gaps for a total of three |
| 53 | +LETTER_SPACE = array.array("H", [LED_OFF | (2 * DAH_DURATION)]) |
| 54 | +# That is, four more DAH-length gaps (after a letter space) for a total of seven |
| 55 | +WORD_SPACE = array.array("H", [LED_OFF | (4 * DIT_DURATION)]) |
| 56 | + |
| 57 | +# Letters and words can be created by concatenating ("+") the elements |
| 58 | +E = DAH + LETTER_SPACE |
| 59 | +O = DAH + DAH + DAH + LETTER_SPACE |
| 60 | +S = DIT + DIT + DIT + LETTER_SPACE |
| 61 | +T = DIT + LETTER_SPACE |
| 62 | +SOS = S + O + S + WORD_SPACE |
| 63 | +TEST = T + E + S + T + WORD_SPACE |
| 64 | + |
| 65 | +# 8 slots of the shortest possible led-off time |
| 66 | +# A background write is 'complete' as soon as all data has been placed |
| 67 | +# in the StateMachine's FIFO. This FIFO has either 4 or 8 entries. |
| 68 | +# By adding 8 very short "led off" times, we can have our 'sm.writing' test |
| 69 | +# tell us when the actual letter data has all been |
| 70 | +FILLER = array.array("H", [LED_OFF | 1]) * 8 |
| 71 | + |
| 72 | +sm = StateMachine( |
| 73 | + pio_code.assembled, |
| 74 | + frequency=1_000_000, |
| 75 | + first_out_pin=LED, |
| 76 | + pull_threshold=16, |
| 77 | + auto_pull=True, |
| 78 | + out_shift_right=False, |
| 79 | +) |
| 80 | + |
| 81 | +# To simply repeat 'TEST' forever, change to 'if True': |
| 82 | +if False: # pylint: disable=using-constant-test |
| 83 | + print("Sending out TEST forever", end="") |
| 84 | + sm.background_write(loop=TEST) |
| 85 | + while True: |
| 86 | + print(end=".") |
| 87 | + time.sleep(0.1) |
| 88 | + |
| 89 | +# But instead, let's alternate SOS and TEST, forever: |
| 90 | + |
| 91 | +while True: |
| 92 | + for plain, morse in ( |
| 93 | + ("SOS", SOS), |
| 94 | + ("TEST", TEST), |
| 95 | + ): |
| 96 | + print(f"Sending out {plain}", end="") |
| 97 | + sm.background_write(morse + FILLER) |
| 98 | + while sm.writing: |
| 99 | + print(end=".") |
| 100 | + time.sleep(0.1) |
| 101 | + print() |
| 102 | + print("Message all sent to StateMachine") |
| 103 | + time.sleep(1) |
| 104 | + print() |
0 commit comments